Merge pull request #703 from mawe42/doc-improvements

API documentation cleanup and improvements
This commit is contained in:
Tom M 2020-11-16 22:57:22 +01:00 committed by GitHub
commit bfe0f26d96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
76 changed files with 6655 additions and 1260 deletions

View file

@ -38,3 +38,60 @@ Find FluidSynth's style guide below. Syntax related issues, like missing braces,
* Every block after an if, else, while or for should be enclosed in braces
* **Allman-Style** braces everywhere
### Documentation Style Guide
We use Doxygen for public API functions, usage examples and other
information.
#### Order of Elements
Please ensure that the order of elements in the documentation block
is consistent with the existing documentation. Most importantly,
each function starts with a single sentence brief description,
followed by any `@param` and `@return` tags. `@deprecated` and
`@since` should always come last.
Example:
```
/**
* Brief description of the function (only a single sentence).
*
* @param ...
* @param ...
* @return ...
*
* Detailed description of the function. This can be multiple paragraphs,
* include code examples etc. It can also include @note, @warning or
* other special tags not mentioned below.
*
* @deprecated This is deprecated because ...
*
* @since 1.2.3
*/
```
#### Mark Lifecycle Functions
All functions are sorted alphabetically in the generated API documentation.
To ensure that the `new_*` and `delete_*` functions appear first, please make
sure to surround those lifecycle functions with `@startlifecycle{}` and
`@endlifecycle` tags.
Example:
```
/** @startlifecycle{Some Name} */
new_fluid_some_name(...);
delete_fluid_some_name(...);
/** @endlifecycle */
```
#### Referencing Setting Items
If you want to mention a setting item (for example `audio.periods`),
please use the custom `@setting{name}` tag. The argument `name` should be
the setting name with all `.` replaced by `_`.
Example:
```
/**
* This is a comment that references \setting{audio_periods}. You
* can also link to a group of settings with \setting{audio} or
* \setting{synth}.
*/
```

View file

@ -27,18 +27,25 @@ if ( DOXYGEN_FOUND )
${DOXYGEN} Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
find_package ( LibXslt )
if ( LIBXSLT_XSLTPROC_EXECUTABLE )
add_custom_target ( doxygen_settings
${LIBXSLT_XSLTPROC_EXECUTABLE}
--output ${CMAKE_CURRENT_BINARY_DIR}/fluidsettings.txt
${CMAKE_CURRENT_SOURCE_DIR}/doxygen/fluidsettings.xsl
${CMAKE_CURRENT_SOURCE_DIR}/fluidsettings.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_dependencies(doxygen doxygen_settings)
endif ( LIBXSLT_XSLTPROC_EXECUTABLE )
endif ( DOXYGEN_FOUND )
if ( UNIX )
install ( FILES fluidsynth.1
DESTINATION ${MAN_INSTALL_DIR} )
endif ( UNIX )
include ( FluidUnitTest )
add_custom_target ( demo )
ADD_FLUID_DEMO ( example )
ADD_FLUID_DEMO ( fluidsynth_arpeggio )
ADD_FLUID_DEMO ( fluidsynth_fx )
ADD_FLUID_DEMO ( fluidsynth_metronome )
ADD_FLUID_DEMO ( fluidsynth_simple )
add_subdirectory ( examples )

View file

@ -11,7 +11,7 @@ CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" "The $name widget" "The $name file" is provides specifies contains represents a an the
ABBREVIATE_BRIEF = "Functions for" "Functions to" "The $name class" "The $name widget" "The $name file" is provides specifies contains represents a an the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
@ -24,7 +24,9 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
ALIASES += startlifecycle{1}="\name Lifecycle Functions for \1\_linebr@{"
ALIASES += endlifecycle="@}"
ALIASES += setting{1}="\ref settings_\1"
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
@ -34,7 +36,7 @@ CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
#---------------------------------------------------------------------------
# Build related configuration options
@ -54,9 +56,9 @@ CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_GROUP_NAMES = NO
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = YES
SORT_GROUP_NAMES = YES
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
@ -82,18 +84,26 @@ WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ../doc/fluidsynth-v20-devdoc.txt ../include ../include/fluidsynth ../src
INPUT = \
../doc/fluidsynth-v20-devdoc.txt \
../doc/recent_changes.txt \
../doc/usage \
../include \
../include/fluidsynth \
../src \
../doc/doxygen/fluidsettings.txt
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c *.h
FILE_PATTERNS = *.c *.h *.txt
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = fluid_*.h
EXCLUDE_SYMBOLS =
EXAMPLE_PATH = ../doc
EXAMPLE_PATH = ../doc/examples
EXAMPLE_PATTERNS = *.c
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
IMAGE_PATH = ../doc/images
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
@ -103,8 +113,8 @@ FILTER_SOURCE_FILES = NO
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = NO
@ -120,11 +130,20 @@ IGNORE_PREFIX =
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_EXTRA_STYLESHEET = ../doc/doxy_formula.css
HTML_ALIGN_MEMBERS = YES
HTML_EXTRA_FILES = ../doc/fluidsettings.xml ../doc/fluidsettings.xsl ../doc/FluidMixer.pdf ../doc/FluidMixer.jpg
HTML_EXTRA_FILES = \
../doc/fluidsettings.xml \
../doc/fluidsettings.xsl
# FluidSynth specific layout and style customizations.
# Comment the following four lines to return to the
# default doxygen styling and layout
LAYOUT_FILE = ../doc/doxygen/layout.xml
HTML_HEADER =
HTML_FOOTER = ../doc/doxygen/footer.html
HTML_EXTRA_STYLESHEET = ../doc/doxygen/custom.css
# end FluidSynth styling and layout
GENERATE_HTMLHELP = NO
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
@ -137,9 +156,9 @@ CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
ENUM_VALUES_PER_LINE = 1
GENERATE_TREEVIEW = YES
TREEVIEW_WIDTH = 350
FORMULA_FONTSIZE = 10
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
@ -195,12 +214,14 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = __DOXYGEN__
PREDEFINED = __DOXYGEN__ \
FLUIDSYNTH_API \
FLUID_DEPRECATED
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------

View file

@ -11,7 +11,7 @@ CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" "The $name widget" "The $name file" is provides specifies contains represents a an the
ABBREVIATE_BRIEF = "Functions for" "Functions to" "The $name class" "The $name widget" "The $name file" is provides specifies contains represents a an the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
@ -24,7 +24,9 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
ALIASES += startlifecycle{1}="\name Lifecycle Functions for \1\_linebr@{"
ALIASES += endlifecycle="@}"
ALIASES += setting{1}="\ref settings_\1"
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
@ -34,7 +36,7 @@ CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
#---------------------------------------------------------------------------
# Build related configuration options
@ -54,9 +56,9 @@ CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_GROUP_NAMES = NO
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = YES
SORT_GROUP_NAMES = YES
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
@ -65,7 +67,6 @@ GENERATE_DEPRECATEDLIST = YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
@ -82,18 +83,27 @@ WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = @CMAKE_SOURCE_DIR@/doc/fluidsynth-v20-devdoc.txt @CMAKE_SOURCE_DIR@/include @CMAKE_SOURCE_DIR@/include/fluidsynth @CMAKE_SOURCE_DIR@/src @CMAKE_BINARY_DIR@/include/fluidsynth
INPUT = \
@CMAKE_SOURCE_DIR@/doc/fluidsynth-v20-devdoc.txt \
@CMAKE_SOURCE_DIR@/doc/recent_changes.txt \
@CMAKE_SOURCE_DIR@/doc/usage \
@CMAKE_SOURCE_DIR@/include \
@CMAKE_SOURCE_DIR@/include/fluidsynth \
@CMAKE_SOURCE_DIR@/src \
@CMAKE_BINARY_DIR@/include/fluidsynth \
@CMAKE_BINARY_DIR@/doc/fluidsettings.txt
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c *.h
FILE_PATTERNS = *.c *.h *.txt
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = fluid_*.h
EXCLUDE_SYMBOLS =
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/doc
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/doc/examples
EXAMPLE_PATTERNS = *.c
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
IMAGE_PATH = @CMAKE_SOURCE_DIR@/doc/images
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
@ -103,8 +113,8 @@ FILTER_SOURCE_FILES = NO
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = NO
@ -120,11 +130,19 @@ IGNORE_PREFIX =
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_EXTRA_STYLESHEET = @CMAKE_SOURCE_DIR@/doc/doxy_formula.css
HTML_ALIGN_MEMBERS = YES
HTML_EXTRA_FILES = @CMAKE_SOURCE_DIR@/doc/fluidsettings.xml @CMAKE_SOURCE_DIR@/doc/fluidsettings.xsl @CMAKE_SOURCE_DIR@/doc/FluidMixer.pdf @CMAKE_SOURCE_DIR@/doc/FluidMixer.jpg
HTML_EXTRA_FILES = \
@CMAKE_SOURCE_DIR@/doc/fluidsettings.xml \
@CMAKE_SOURCE_DIR@/doc/fluidsettings.xsl
# FluidSynth specific layout and style customizations.
# Comment the following four lines to return to the
# default doxygen styling and layout
LAYOUT_FILE = @CMAKE_SOURCE_DIR@/doc/doxygen/layout.xml
HTML_HEADER =
HTML_FOOTER = @CMAKE_SOURCE_DIR@/doc/doxygen/footer.html
HTML_EXTRA_STYLESHEET = @CMAKE_SOURCE_DIR@/doc/doxygen/custom.css
# end FluidSynth styling and layout
GENERATE_HTMLHELP = NO
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
@ -137,9 +155,9 @@ CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
ENUM_VALUES_PER_LINE = 1
GENERATE_TREEVIEW = YES
TREEVIEW_WIDTH = 350
FORMULA_FONTSIZE = 10
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
@ -177,8 +195,6 @@ MAN_LINKS = NO
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
@ -195,12 +211,14 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = __DOXYGEN__
PREDEFINED = __DOXYGEN__ \
FLUIDSYNTH_API \
FLUID_DEPRECATED
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
@ -218,7 +236,7 @@ CLASS_DIAGRAMS = YES
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_FONTNAME = FreeSans
DOT_FONTNAME =
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

View file

@ -1,12 +0,0 @@
code {
background-color: #eeeeee;
text-shadow: none;
color: black;
margin-left: 4px;
margin-right: 4px;
padding-left: 4px;
padding-right: 4px;
border-radius: 3px;
white-space: nowrap;
}

282
doc/doxygen/custom.css Normal file
View file

@ -0,0 +1,282 @@
body
{
background: #eee;
}
#titlearea
{
background: white;
}
*
{
text-shadow: none !important;
}
/* Reduce width of main content for more readibility */
div.contents,
div.header
{
max-width: 60em;
background: white;
margin: 0;
padding: 1em;
}
#titlearea
{
border: 0;
}
div.headertitle
{
padding-left: 0;
}
/* Hide permalink icon in front of method name and make whole name clickable
* instead (by invisibly streting the permalink over the title). Not ideal,
* as the name can't be selected anymore, but better than the distracting
* icon. */
span.permalink
{
display: block;
position: relative;
font-size: unset;
}
span.permalink a {
position: absolute;
width: 100%;
opacity: 0;
}
/* Hide "libfluidsynth" root node of nav tree */
#nav-tree-contents > ul > li:first-child > .item > .label,
#nav-tree-contents > ul > li:first-child > .item > a
{
display: none;
}
#nav-tree,
#side-nav
{
background: #333;
}
#nav-tree .label a {
color: #fff;
}
#nav-tree .selected {
background: #666;
}
#side-nav {
width: 350px;
}
.ui-resizable-e {
background: #ddd;
}
#nav-sync {
display: none;
}
@media (max-width: 767px) {
#side-nav {
display: none !important;
}
#doc-content {
margin-left: 0 !important;
height: auto !important;
width: auto !important;
}
#MSearchBox {
display: none !important;
}
}
.sm-dox a:hover {
color: black !important;
}
#nav-tree,
div.header,
.ui-resizable-e,
.sm-dox,
.navpath ul,
.memtitle,
.sm-dox a,
.fieldtable th
{
background-image: none !important;
}
#main-nav {
background: #DFE5F1;
}
.memitem,
.memproto,
.memdoc,
.memtitle,
dl.reflist dd,
dl.reflist dt
{
box-shadow: none;
text-shadow: none;
border-right: none;
border-bottom: none;
border-bottom-left-radius: 0;
background-image: none;
border-color: #DFE5F1;
}
.memtitle,
dl.reflist dt
{
width: 100%;
box-sizing: border-box;
background: #DFE5F1;
border: 0;
}
.memproto {
background: #fafafa;
border-bottom: 1px solid #DFE5F1;
border-right: 1px solid #DFE5F1;
}
.mdescLeft,
.mdescRight,
.memItemLeft,
.memItemRight,
.memTemplItemLeft,
.memTemplItemRight,
.memTemplParams
{
background: none;
}
.memSeparator {
}
dl.reflist {
padding: 0;
}
dl.reflist dd {
margin-bottom: 1.5em;
padding: 1em;
}
code {
background-color: #eeeeee;
text-shadow: none;
color: black;
margin-left: 4px;
margin-right: 4px;
padding-left: 4px;
padding-right: 4px;
border-radius: 3px;
white-space: nowrap;
}
table.fieldtable,
table.fieldtable td,
table.fieldtable th
{
box-shadow: none;
text-shadow: none;
border-radius: 0;
border-color: #DFE5F1 !important;
}
div.fragment {
padding: 5px;
}
div.fragment .line {
line-height: 1.4;
}
.memdoc dl {
padding-left: 0;
}
dl.note {
margin-left: -10px;
padding-left: 5px;
border-left: 5px solid;
border-color: lightblue;
}
dl.deprecated {
margin-left: -10px;
padding-left: 5px;
border-left: 5px solid;
border-color: orange;
}
dl.warning {
margin-left: -10px;
padding-left: 5px;
border-left: 5px solid;
border-color: red;
}
table.directory .arrow {
height: inherit;
}
table.directory tr td {
padding: 0.4em 6px;
}
table.directory td.desc {
border: 0;
}
table.directory tr.even {
background-color: inherit;
}
table.directory tr {
border-bottom: 1px solid #eee;
}
.image img,
.image object
{
width: 100%;
height: auto;
}
.setting-item {
border-left: 1px solid #DFE5F1;
padding-bottom: 0.5em;
border-top-left-radius: 4px;
}
.setting-item h1 {
width: 100%;
padding: 0.3em 0 0.3em 10px;
box-sizing: border-box;
background: #DFE5F1;
border: 0;
font-size: 1.5em;
font-weight: normal;
border-top-right-radius: 4px;
border-top-left-radius: 4px;
}
.setting-item dl,
.setting-item p {
margin-left: 10px;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" omit-xml-declaration="yes" indent="no"/>
<!-- main template -->
<xsl:template match="/fluidsettings">
/*!
\page fluidsettings Settings Reference
<xsl:apply-templates match="*" mode="PageRef">
<xsl:sort select="@label"/>
</xsl:apply-templates>
<xsl:apply-templates match="*" mode="Page">
<xsl:sort select="@label"/>
</xsl:apply-templates>
*/
</xsl:template>
<!-- Page reference template -->
<xsl:template match="*" mode="PageRef">
- \subpage <xsl:value-of select="concat('settings_', name(.), ' ', @label)"/>
</xsl:template>
<!-- Page template -->
<xsl:template match="*" mode="Page">
\page <xsl:value-of select="concat('settings_', name(.), ' ', @label)"/>
<xsl:apply-templates match="*" mode="Setting">
<xsl:sort select="name(..)" />
</xsl:apply-templates>
</xsl:template>
<!-- Setting template -->
<xsl:template match="*" mode="Setting">
\htmlonly
<div class="setting-item">
\endhtmlonly
\section <xsl:value-of select="concat('settings_', name(..), '_', translate(name, '.', '_'))" /><xsl:text> </xsl:text><xsl:value-of select="concat(name(..), '.', name)" />
<xsl:text>&#xa;</xsl:text>
\par Type
<xsl:choose>
<xsl:when test="type = 'bool'">Boolean (int)</xsl:when>
<xsl:when test="type = 'int'">Integer (int)</xsl:when>
<xsl:when test="type = 'str'">
<xsl:choose>
<xsl:when test="vals">Selection (str)</xsl:when>
<xsl:otherwise>String (str)</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="type = 'num'">Float (num)</xsl:when>
<xsl:otherwise><xsl:value-of select="type" /></xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="type = 'str' and vals">\par Options
<xsl:value-of select="vals" /></xsl:when>
<xsl:when test="type = 'bool'">\par Values
0, 1</xsl:when>
<xsl:when test="min or max">\par Min - Max
<xsl:value-of select="min" /> - <xsl:value-of select="max" /></xsl:when>
</xsl:choose>
\par Default
\htmlonly
<xsl:copy-of select="def" />
\endhtmlonly
<xsl:if test="realtime">
\par Real-time
<xsl:choose>
<xsl:when test="realtime/text()">
\htmlonly
<xsl:copy-of select="realtime" />
\endhtmlonly
</xsl:when>
<xsl:otherwise>This setting can be changed during runtime of the synthesizer.</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test="deprecated">
\deprecated This setting is deprecated and might be removed in a future version of FluidSynth.
</xsl:if>
\htmlonly
<xsl:copy-of select="desc"/>
\endhtmlonly
\htmlonly
</div>
\endhtmlonly
</xsl:template>
</xsl:stylesheet>

2
doc/doxygen/footer.html Normal file
View file

@ -0,0 +1,2 @@
</body>
</html>

199
doc/doxygen/layout.xml Normal file
View file

@ -0,0 +1,199 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.13 -->
<!-- Navigation index tabs for HTML output -->
<!-- FluidSynth related changes in this file compared to default layout:
- Custom title and intro for <navindev><tab type="modules">
- <membergroups> moved in front of <functions> in group layout so that we can change
constructors and destructors before all other functions
-->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="modules" visible="yes" title="API Reference" intro="Reference of the FluidSynth API separated into functional groups."/>
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="yes" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="examples" visible="yes" title="" intro=""/>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<classes visible="yes" title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<classes visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<membergroups visible="yes"/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>

View file

@ -0,0 +1,30 @@
# FluidSynth - A Software Synthesize
#
# 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>
include ( FluidUnitTest )
add_custom_target ( demo )
ADD_FLUID_DEMO ( example )
ADD_FLUID_DEMO ( fluidsynth_arpeggio )
ADD_FLUID_DEMO ( fluidsynth_fx )
ADD_FLUID_DEMO ( fluidsynth_metronome )
ADD_FLUID_DEMO ( fluidsynth_simple )

View file

@ -11,7 +11,14 @@ NOTE: You're not expected to look at this raw XML file. Please open it in a webb
https://stackoverflow.com/a/3839054
https://stackoverflow.com/a/6251757
Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</deprecated>
Developers:
- Settings can be deprecated by adding: <deprecated>SOME TEXT</deprecated>
- Real-time settings can be marked with <realtime>SOME OPTIONAL TEXT</realtime>.
ATTENTION: if you change anything in this file, make sure you also refresh
the doxygen/fluidsettings.txt file (used by fluidsynth.org API doc build)
and commit the results. Refresh with the following command:
xsltproc -o doxygen/fluidsettings.txt doxygen/fluidsettings.xsl fluidsettings.xml
-->
<?xml-stylesheet type="text/xsl" href="fluidsettings.xsl"?>
<fluidsettings>
@ -38,6 +45,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<name>chorus.active</name>
<type>bool</type>
<def>1 (TRUE)</def>
<realtime/>
<desc>
When set to 1 (TRUE) the chorus effects module is activated. Otherwise, no chorus will be added to the output signal. Note that the amount of signal sent to the chorus module depends on the "chorus send" generator defined in the SoundFont.</desc>
</setting>
@ -47,6 +55,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>8.0</def>
<min>0.0</min>
<max>256.0</max>
<realtime/>
<desc>
Specifies the modulation depth of the chorus.</desc>
</setting>
@ -56,6 +65,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>2.0</def>
<min>0.0</min>
<max>10.0</max>
<realtime/>
<desc>
Specifies the output amplitude of the chorus signal.</desc>
</setting>
@ -65,6 +75,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>3</def>
<min>0</min>
<max>99</max>
<realtime/>
<desc>
Sets the voice count of the chorus.</desc>
</setting>
@ -74,6 +85,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>0.3</def>
<min>0.1</min>
<max>5.0</max>
<realtime/>
<desc>
Sets the modulation speed in Hz.</desc>
</setting>
@ -102,6 +114,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>0</def>
<min>0</min>
<max>126</max>
<realtime/>
<desc>
Device identifier used for SYSEX commands, such as MIDI Tuning Standard commands. Only those SYSEX commands destined for this ID or to all devices will be acted upon.</desc>
</setting>
@ -136,6 +149,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>0.2</def>
<min>0.0</min>
<max>10.0</max>
<realtime/>
<desc>The gain is applied to the final or master output of the synthesizer. It is set to a low value by default to avoid the saturation of the output when many notes are played.</desc>
</setting>
<setting>
@ -191,6 +205,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>1000.0</def>
<min>-10000.0</min>
<max>10000.0</max>
<realtime/>
<desc>
This score is divided by the number of seconds this voice has been
active and is added to the overflow priority. It is usually a positive
@ -204,6 +219,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>5000.0</def>
<min>-50000.0</min>
<max>50000.0</max>
<realtime/>
<desc>
This score is added to voices on channels marked with the
synth.overflow.important-channels setting.
@ -213,6 +229,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<name>overflow.important-channels</name>
<type>str</type>
<def>(empty string)</def>
<realtime/>
<desc>
This setting is a comma-separated list of MIDI channel numbers that should
be treated as "important" by the overflow calculation, adding the score
@ -229,6 +246,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>4000.0</def>
<min>-10000.0</min>
<max>10000.0</max>
<realtime/>
<desc>
Sets the overflow priority score added to voices on a percussion
channel. This is usually a positive score, to give percussion voices
@ -242,6 +260,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>-2000.0</def>
<min>-10000.0</min>
<max>10000.0</max>
<realtime/>
<desc>
Sets the overflow priority score added to voices that have already
received a note-off event. This is usually a negative score, to give released
@ -255,6 +274,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>-1000.0</def>
<min>-10000.0</min>
<max>10000.0</max>
<realtime/>
<desc>
Sets the overflow priority score added to voices that are currently
sustained. With the default value, sustained voices are considered less
@ -267,6 +287,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>500.0</def>
<min>-10000.0</min>
<max>10000.0</max>
<realtime/>
<desc>
Sets the overflow priority score added to voices based on their current
volume. The voice volume is normalized to a value between 0 and 1 and
@ -281,6 +302,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>256</def>
<min>1</min>
<max>65535</max>
<realtime/>
<desc>
The polyphony defines how many voices can be played in parallel. A note event produces one or more voices. Its good to set this to a value which the system can handle and will thus limit FluidSynth's CPU usage. When FluidSynth runs out of voices it will begin terminating lower priority voices for new note events.</desc>
</setting>
@ -288,6 +310,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<name>reverb.active</name>
<type>bool</type>
<def>1 (TRUE)</def>
<realtime/>
<desc>
When set to 1 (TRUE) the reverb effects module is activated. Otherwise, no reverb will be added to the output signal. Note that the amount of signal sent to the reverb module depends on the "reverb send" generator defined in the SoundFont.
</desc>
@ -298,6 +321,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>0.0</def>
<min>0.0</min>
<max>1.0</max>
<realtime/>
<desc>
Sets the amount of reverb damping.</desc>
</setting>
@ -307,6 +331,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>0.9</def>
<min>0.0</min>
<max>1.0</max>
<realtime/>
<desc>
Sets the reverb output amplitude.</desc>
</setting>
@ -316,6 +341,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>0.2</def>
<min>0.0</min>
<max>1.0</max>
<realtime/>
<desc>
Sets the room size (i.e. amount of wet) reverb.</desc>
</setting>
@ -325,6 +351,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<def>0.5</def>
<min>0.0</min>
<max>100.0</max>
<realtime/>
<desc>
Sets the stereo spread of the reverb signal.</desc>
</setting>
@ -691,6 +718,7 @@ Developers: Settings can be deprecated by adding: <deprecated>SOME TEXT</depreca
<name>reset-synth</name>
<type>bool</type>
<def>1 (TRUE)</def>
<realtime/>
<desc>If true, reset the synth before starting a new MIDI song, so the state of a previous song can't affect the new song. Turn it off for seamless looping of a song.</desc>
</setting>
<setting>

View file

@ -276,6 +276,22 @@ a {
<div class="value"><xsl:copy-of select="def" /></div>
</div>
<xsl:if test="realtime">
<div class="setting-attribute">
<div class="label">Real-time:</div>
<div class="value">
<xsl:choose>
<xsl:when test="realtime/text()">
<xsl:copy-of select="realtime"/>
</xsl:when>
<xsl:otherwise>
This setting can be changed during runtime of the synthesizer.
</xsl:otherwise>
</xsl:choose>
</div>
</div>
</xsl:if>
<xsl:if test="deprecated">
<div class="setting-deprecated">
This setting is deprecated and might be removed in a future version of FluidSynth.

View file

@ -17,45 +17,13 @@ All the source code examples in this document are in the public domain; you can
<a href="http://www.fluidsynth.org">FluidSynth</a> is a software synthesizer based on the <a href="http://en.wikipedia.org/wiki/SoundFont">SoundFont 2</a> specifications. The synthesizer is available as a shared object that can easily be reused in any application that wants to use wave-table synthesis. This document explains the basic usage of FluidSynth. Some of the more advanced features are not yet discussed but will be added in future versions.
\section Contents Table of Contents
- \ref Disclaimer
- \ref Introduction
- \ref NewIn2_2_0
- \ref NewIn2_1_4
- \ref NewIn2_1_1
- \ref NewIn2_1_0
- \ref NewIn2_0_8
- \ref NewIn2_0_7
- \ref NewIn2_0_6
- \ref NewIn2_0_5
- \ref NewIn2_0_3
- \ref NewIn2_0_2
- \ref NewIn2_0_0
- \ref CreatingSettings
- \ref CreatingSynth
- \ref CreatingAudioDriver
- \ref UsingSynth
- \ref LoadingSoundfonts
- \ref SendingMIDI
- \ref RealtimeMIDI
- \ref MIDIPlayer
- \ref FileRenderer
- \ref MIDIPlayerMem
- \ref MIDIRouter
- \ref Sequencer
- \ref Shell
- \ref Multi-channel
- \ref synth-context
- \ref Advanced
\section Disclaimer
This documentation may be partly incomplete. As always, the source code is the final reference.
SoundFont(R) is a registered trademark of E-mu Systems, Inc.
\section Introduction
\page Introduction Introduction
What is FluidSynth?
@ -71,730 +39,13 @@ What is FluidSynth?
- FluidSynth is open source, in active development. For more details, take a look at http://www.fluidsynth.org
\section NewIn2_2_0 What's new in 2.2.0?
- #fluid_file_callbacks_t now uses <code>long long</code> as file-offset type (see #fluid_long_long_t). This is a breaking change, which allows to load SoundFonts bigger than 2GiB on Windows. This change required to bump fluidsynth's SOVERSION.
- fluid_event_any_control_change() has been removed
- various fluid_event_*() functions that received a "value" argument of type <code>short</code> now receive an <code>int</code> argument in preparation for MIDI 2.0 support
- The sequencer has received a major revisal. For you that means:
- The sequencer's queue no longer blocks the synthesizer thread, due to being busy arranging its events internally.
- Events that share the same tick was given a new, documented order, see fluid_sequencer_send_at().
- The sequencer's scale can now be used for arbitrary tempo changes. Previously, the scale of the sequencer was limited to 1000. The only limitation now is >0.
- The dynamic-sample-loader has learned support to pin samples, see fluid_synth_pin_preset() and fluid_synth_unpin_preset()
\page deprecated Deprecated Functions
\section NewIn2_1_4 What's new in 2.1.4?
This page contains functions that have been marked obsolete.
Functions listed here will be removed in the next major release.
It is therefore not wise to use them in new code.
- a regression introduced in 2.1.3 broke fluid_synth_start() for DLS presets
\section NewIn2_1_1 What's new in 2.1.1?
- requirements for explicit sequencer client unregistering have been relaxed: delete_fluid_sequencer() now correctly frees any registered sequencer clients (clients can still be explicitly unregistered)
- using the sequencer with the system timer as timing source has been deprecated
\section NewIn2_1_0 What's new in 2.1.0?
- <span style="color:red">refrain from using fluid_synth_set_sample_rate()</span>
- <a href="www.fluidsynth.org/api/fluidsettings.xml#synth.sample-rate">synth.sample-rate</a> is no real-time setting anymore, see note about fluid_synth_set_sample_rate()
- new reverb engine
- chorus is now stereophonic
- smallest allowed chorus speed is now 0.1 Hz (previously 0.29 Hz)
- the following audio drivers were added:
- opensles
- oboe
- sdl2
- waveout
\section NewIn2_0_8 What's new in 2.0.8?
- fluid_sample_set_sound_data() caused broken sound when copying sample data
\section NewIn2_0_7 What's new in 2.0.7?
- fluid_free() has been added to allow proper deallocation by programming languages other than C/C++
\section NewIn2_0_6 What's new in 2.0.6?
- the MIDI player did not emit any audio when calling fluid_player_play() after fluid_player_stop()
\section NewIn2_0_5 What's new in 2.0.5?
- fluid_synth_process() omitted audio samples when called with arbitrary sample counts that were not a multiple of fluid_synth_get_internal_bufsize()
- fluid_synth_sfunload() was not releasing sample buffers of SoundFont3 files if <a href="fluidsettings.xml#synth.dynamic-sample-loading">"synth.dynamic-sample-loading"</a> was set to FALSE
\section NewIn2_0_3 What's new in 2.0.3?
- fix incorrect behaviour of fluid_sample_set_sound_data()
- add missing getters for midi events:
- fluid_midi_event_get_text()
- fluid_midi_event_get_lyrics()
\section NewIn2_0_2 What's new in 2.0.2?
- fluid_synth_error() has been deprecated, use fluid_set_log_function() to interfere log messages
\section NewIn2_0_0 What's new in 2.0.0?
FluidSynths major version was bumped. The API was reworked, deprecated functions were removed.
<strong><span style="color:red">Important changes that may not result in a compilation error but may cause your app to misbehave:</span></strong>
- all public \c fluid_settings_* functions that return an integer which is not meant to be interpreted as bool consistently return either FLUID_OK or FLUID_FAILED
- fluid_settings_setstr() cannot be used to set integer (toggle) settings with "yes" or "no" values anymore. Use fluid_settings_setint() instead, for example: <br /><code>fluid_settings_setint(settings, "synth.reverb.active", 0)</code> instead of <code>fluid_settings_setstr(settings, "synth.reverb.active", "no")</code>
- <span style="text-decoration:line-through;">explicit client unregistering is required for fluid_sequencer_register_client() and fluid_sequencer_register_fluidsynth()</span> (since fluidsynth 2.1.1 not required anymore, but still recommend)
- all public functions consistently receive signed integers for soundfont ids, bank and program numbers
- use unique device names for the "audio.portaudio.device" setting
- fluid_synth_process() received a new more flexible implementation, but now requires zeroed-out sample buffers
<strong>Other changes in FluidSynth 2.0.0 concerning developers:</strong>
- all public \c delete_* functions return void and are safe when called with NULL
- the shell command handler was decoupled internally, as a consequence the param list of new_fluid_server() and new_fluid_cmd_handler() was adapted
- \c fluid_settings_set* functions no longer silently register unknown settings but return an error instead
- reverb: roomsize is now limited to an upper threshold of 1.0 to avoid exponential volume increase
- rename \c fluid_mod_new() and \c fluid_mod_delete() to match naming conventions: new_fluid_mod() and delete_fluid_mod()
- rename chorus getters to match naming conventions: fluid_synth_get_chorus_speed() and fluid_synth_get_chorus_depth()
- fluid_synth_remove_sfont() returns FLUID_OK or FLUID_FAILED
- introduce a separate data type for sequencer client IDs: #fluid_seq_id_t
- fluid_get_userconf() has been implemented for Windows
<strong>New Features and API additions:</strong>
- add <a href="fluidsettings.xml#midi.autoconnect">"midi.autoconnect"</a> a setting for automatically connecting fluidsynth to available MIDI input ports
- add <a href="fluidsettings.xml#synth.overflow.important">"synth.overflow.important"</a> and <a href="fluidsettings.xml#synth.overflow.important-channels">"synth.overflow.important-channels"</a> settings to take midi channels during overflow calculation into account that are considered to be "important"
- add <a href="fluidsettings.xml#synth.dynamic-sample-loading">"synth.dynamic-sample-loading"</a> a setting for enabling on demand sample loading
- add support for polyphonic key pressure events, see fluid_event_key_pressure() and fluid_synth_key_pressure()
- add fluid_synth_add_default_mod() and fluid_synth_remove_default_mod() for manipulating default modulators
- add individual reverb setters: fluid_synth_set_reverb_roomsize(), fluid_synth_set_reverb_damp(), fluid_synth_set_reverb_width(), fluid_synth_set_reverb_level()
- add individual chorus setters: fluid_synth_set_chorus_nr(), fluid_synth_set_chorus_level(), fluid_synth_set_chorus_speed(), fluid_synth_set_chorus_depth(), fluid_synth_set_chorus_type()
- add realtime settings for <a href="fluidsettings.xml#synth.reverb.damp">reverb</a> and <a href="fluidsettings.xml#synth.chorus.depth">chorus</a> parameters
- add seek support to midi-player, see fluid_player_seek()
- expose functions to manipulate the ladspa effects unit (see ladspa.h)
- add support for text and lyrics midi events, see fluid_midi_event_set_lyrics() and fluid_midi_event_set_text()
- complete rewrite of the soundfont loader API, see sfont.h
- support for 24 bit audio samples, see fluid_sample_set_sound_data()
- expose new_fluid_defsfloader() to support loading soundfonts from memory, see fluid_sfloader_set_callbacks() and <a href="fluidsynth_sfload_mem_8c-example.html">fluidsynth_sfload_mem.c</a>
- remove these structs from the public API and provide proper getter and setter functions instead:
- struct _fluid_sfloader_t
- struct _fluid_sample_t
- struct _fluid_sfont_t
- struct _fluid_preset_t
- add an additional general-purpose IIR filter, see fluid_synth_set_custom_filter()
- add a custom sinusoidal modulator mapping function, see #FLUID_MOD_SIN
- implement polymono support according to MIDI specs:
- add basic channel support, see fluid_synth_reset_basic_channel(), fluid_synth_set_basic_channel(), fluid_synth_get_basic_channel()
- implement MIDI modes Omni On, Omni Off, Poly, Mono, see #fluid_basic_channel_modes
- implement portamento control, see fluid_synth_set_portamento_mode(), fluid_synth_get_portamento_mode()
- implement legato control, see fluid_synth_set_legato_mode(), fluid_synth_get_legato_mode()
- implement breath control, see fluid_synth_set_breath_mode(), fluid_synth_get_breath_mode()
<strong>API cleanups:</strong>
- the ramsfont has been removed, because it is unmaintained and believed to be unused; please get in touch with the mailing list if you still need it
- remove deprecated fluid_synth_get_channel_info() in favour of fluid_synth_get_program() and fluid_synth_get_channel_preset()
- remove deprecated fluid_settings_getstr()
- remove deprecated fluid_synth_set_midi_router(), instead supply the midi-router instance when creating a command handler with new_fluid_cmd_handler()
- remove deprecated fluid_get_hinstance() and fluid_set_hinstance() (dsound driver now uses the desktop window)
- remove deprecated fluid_synth_create_key_tuning(), use fluid_synth_activate_key_tuning(synth, bank, prog, name, pitch, FALSE) instead
- remove deprecated fluid_synth_create_octave_tuning(), use fluid_synth_activate_octave_tuning(synth, bank, prog, name, pitch, FALSE) instead
- remove deprecated fluid_synth_select_tuning(), use fluid_synth_activate_tuning(synth, chan, bank, prog, FALSE) instead
- remove deprecated fluid_synth_reset_tuning(), use fluid_synth_deactivate_tuning(synth, chan, FALSE) instead
- remove deprecated FLUID_HINT_INTEGER
- remove deprecated fluid_synth_set_gen2() as there doesn't seem to be a use case for absolute generator values
- remove deprecated "synth.parallel-render" setting
- remove obsolete "audio.[out|in]put-channels" settings
- remove unimplemented "synth.dump" setting
- remove fluid_cmd_handler_register() and fluid_cmd_handler_unregister() from public API, as they seem to be unused downstream
- remove misspelled FLUID_SEQ_PITCHWHHELSENS macro
- remove struct _fluid_mod_t from public API, use the getters and setters of mod.h instead
- remove struct _fluid_gen_t, fluid_gen_set_default_values() and enum fluid_gen_flags from public API
- remove macros fluid_sfont_get_id() and fluid_sample_refcount() from public API
- remove FLUID_NUM_MOD macro from public API
- remove the following deprecated enum values from public API:
- GEN_LAST
- LAST_LOG_LEVEL
- FLUID_SEQ_LASTEVENT
- FLUID_MIDI_ROUTER_RULE_COUNT
\section CreatingSettings Creating and changing the settings
Before you can use the synthesizer, you have to create a settings object. The settings objects is used by many components of the FluidSynth library. It gives a unified API to set the parameters of the audio drivers, the midi drivers, the synthesizer, and so forth. A number of default settings are defined by the current implementation.
All settings have a name that follows the "dotted-name" notation. For example, "synth.polyphony" refers to the number of voices (polyphony) allocated by the synthesizer. The settings also have a type. There are currently three types: strings, numbers (double floats), and integers. You can change the values of a setting using the fluid_settings_setstr(), fluid_settings_setnum(), and fluid_settings_setint() functions. For example:
\code
#include <fluidsynth.h>
int main(int argc, char** argv)
{
fluid_settings_t* settings = new_fluid_settings();
fluid_settings_setint(settings, "synth.polyphony", 128);
/* ... */
delete_fluid_settings(settings);
return 0;
}
\endcode
The API contains the functions to query the type, the current value, the default value, the range and the "hints" of a setting. The range is the minimum and maximum value of the setting. The hints gives additional information about a setting. For example, whether a string represents a filename. Or whether a number should be interpreted on on a logarithmic scale. Check the settings.h API documentation for a description of all functions.
\section CreatingSynth Creating the synthesizer
To create the synthesizer, you pass it the settings object, as in the following example:
\code
#include <fluidsynth.h>
int main(int argc, char** argv)
{
fluid_settings_t* settings;
fluid_synth_t* synth;
settings = new_fluid_settings();
synth = new_fluid_synth(settings);
/* Do useful things here */
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return 0;
}
\endcode
For a full list of available <strong>synthesizer settings</strong>, please refer to <a href="fluidsettings.xml" target="_blank"><b>FluidSettings Documentation</b></a>.
\section CreatingAudioDriver Creating the Audio Driver
The synthesizer itself does not write any audio to the audio output. This allows application developers to manage the audio output themselves if they wish. The next section describes the use of the synthesizer without an audio driver in more detail.
Creating the audio driver is straightforward: set the <code>audio.driver</code> settings and create the driver object. Because the FluidSynth has support for several audio systems, you may want to change which one you want to use. The list below shows the audio systems that are currently supported. It displays the name, as used by the fluidsynth library, and a description.
- jack: JACK Audio Connection Kit (Linux, Mac OS X, Windows)
- alsa: Advanced Linux Sound Architecture (Linux)
- oss: Open Sound System (Linux, Unix)
- pulseaudio: PulseAudio (Linux, Mac OS X, Windows)
- coreaudio: Apple CoreAudio (Mac OS X)
- dsound: Microsoft DirectSound (Windows)
- portaudio: PortAudio Library (Mac OS 9 & X, Windows, Linux)
- sndman: Apple SoundManager (Mac OS Classic)
- dart: DART sound driver (OS/2)
- opensles: OpenSL ES (Android)
- oboe: Oboe (Android)
- waveout: Microsoft WaveOut, alternative to DirectSound (Windows CE x86, Windows Mobile 2003 for ARMv5, Windows 98 SE, Windows NT 4.0, Windows XP and later)
- file: Driver to output audio to a file
- sdl2*: Simple DirectMedia Layer (Linux, Windows, Mac OS X, iOS, Android, FreeBSD, Haiku, etc.)
The default audio driver depends on the settings with which FluidSynth was compiled. You can get the default driver with fluid_settings_getstr_default(). To get the list of available drivers use the fluid_settings_foreach_option() function. Finally, you can set the driver with fluid_settings_setstr(). In most cases, the default driver should work out of the box.
Additional options that define the audio quality and latency are "audio.sample-format", "audio.period-size", and "audio.periods". The details are described later.
You create the audio driver with the new_fluid_audio_driver() function. This function takes the settings and synthesizer object as arguments. For example:
\code
void init()
{
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_audio_driver_t* adriver;
settings = new_fluid_settings();
/* Set the synthesizer settings, if necessary */
synth = new_fluid_synth(settings);
fluid_settings_setstr(settings, "audio.driver", "jack");
adriver = new_fluid_audio_driver(settings, synth);
}
\endcode
As soon as the audio driver is created, it will start playing. The audio driver creates a separate thread that uses the synthesizer object to generate the audio.
There are a number of general audio driver settings. The audio.driver settings define the audio subsystem that will be used. The audio.periods and audio.period-size settings define the latency and robustness against scheduling delays. There are additional settings for the audio subsystems used. For a full list of available <strong>audio driver settings</strong>, please refer to <a href="fluidsettings.xml" target="_blank"><strong>FluidSettings Documentation</strong></a>.
<strong>*Note:</strong> In order to use sdl2 as audio driver, the application is responsible for initializing SDL (e.g. with SDL_Init()). This must be done <strong>before</strong> the first call to <code>new_fluid_settings()</code>! Also make sure to call SDL_Quit() after all fluidsynth instances have been destroyed.
\section UsingSynth Using the synthesizer without an audio driver
It is possible to use the synthesizer object without creating an audio driver. This is desirable if the application using FluidSynth manages the audio output itself. The synthesizer has several API functions that can be used to obtain the audio output:
fluid_synth_write_s16() fills two buffers (left and right channel) with samples coded as signed 16 bits (the endian-ness is machine dependent). fluid_synth_write_float() fills a left and right audio buffer with 32 bits floating point samples. The function fluid_synth_process() is the generic interface for synthesizing audio, which is also capable of multi channel audio output.
\section LoadingSoundfonts Loading and managing SoundFonts
Before any sound can be produced, the synthesizer needs a SoundFont.
SoundFonts are loaded with the fluid_synth_sfload() function. The function takes the path to a SoundFont file and a boolean to indicate whether the presets of the MIDI channels should be updated after the SoundFont is loaded. When the boolean value is TRUE, all MIDI channel bank and program numbers will be refreshed, which may cause new instruments to be selected from the newly loaded SoundFont.
The synthesizer can load any number of SoundFonts. The loaded SoundFonts are treated as a stack, where each new loaded SoundFont is placed at the top of the stack. When selecting presets by bank and program numbers, SoundFonts are searched beginning at the top of the stack. In the case where there are presets in different SoundFonts with identical bank and program numbers, the preset from the most recently loaded SoundFont is used. The fluid_synth_program_select() can be used for unambiguously selecting a preset or bank offsets could be applied to each SoundFont with fluid_synth_set_bank_offset(), to try and ensure that each preset has unique bank and program numbers.
The fluid_synth_sfload() function returns the unique identifier of the loaded SoundFont, or -1 in case of an error. This identifier is used in subsequent management functions: fluid_synth_sfunload() removes the SoundFont, fluid_synth_sfreload() reloads the SoundFont. When a SoundFont is reloaded, it retains it's ID and position on the SoundFont stack.
Additional API functions are provided to get the number of loaded SoundFonts and to get a pointer to the SoundFont.
\section SendingMIDI Sending MIDI Events
Once the synthesizer is up and running and a SoundFont is loaded, most people will want to do something useful with it. Make noise, for example. MIDI messages can be sent using the fluid_synth_noteon(), fluid_synth_noteoff(), fluid_synth_cc(), fluid_synth_pitch_bend(), fluid_synth_pitch_wheel_sens(), and fluid_synth_program_change() functions. For convenience, there's also a fluid_synth_bank_select() function (the bank select message is normally sent using a control change message).
The following example show a generic graphical button that plays a note when clicked:
\code
class SoundButton : public SomeButton
{
public:
SoundButton() : SomeButton() {
if (!_synth) {
initSynth();
}
}
static void initSynth() {
_settings = new_fluid_settings();
_synth = new_fluid_synth(_settings);
_adriver = new_fluid_audio_driver(_settings, _synth);
}
/* ... */
virtual int handleMouseDown(int x, int y) {
/* Play a note on key 60 with velocity 100 on MIDI channel 0 */
fluid_synth_noteon(_synth, 0, 60, 100);
}
virtual int handleMouseUp(int x, int y) {
/* Release the note on key 60 */
fluid_synth_noteoff(_synth, 0, 60);
}
protected:
static fluid_settings_t* _settings;
static fluid_synth_t* _synth;
static fluid_audio_driver_t* _adriver;
};
\endcode
\section RealtimeMIDI Creating a Real-time MIDI Driver
FluidSynth can process real-time MIDI events received from hardware MIDI ports or other applications. To do so, the client must create a MIDI input driver. It is a very similar process to the creation of the audio driver: you initialize some properties in a settings instance and call the new_fluid_midi_driver() function providing a callback function that will be invoked when a MIDI event is received. The following MIDI drivers are currently supported:
- jack: JACK Audio Connection Kit MIDI driver (Linux, Mac OS X)
- oss: Open Sound System raw MIDI (Linux, Unix)
- alsa_raw: ALSA raw MIDI interface (Linux)
- alsa_seq: ALSA sequencer MIDI interface (Linux)
- winmidi: Microsoft Windows MM System (Windows)
- midishare: MIDI Share (Linux, Mac OS X)
- coremidi: Apple CoreMIDI (Mac OS X)
\code
#include <fluidsynth.h>
int handle_midi_event(void* data, fluid_midi_event_t* event)
{
printf("event type: %d\n", fluid_midi_event_get_type(event));
}
int main(int argc, char** argv)
{
fluid_settings_t* settings;
fluid_midi_driver_t* mdriver;
settings = new_fluid_settings();
mdriver = new_fluid_midi_driver(settings, handle_midi_event, NULL);
/* ... */
delete_fluid_midi_driver(mdriver);
return 0;
}
\endcode
There are a number of general MIDI driver settings. The midi.driver setting
defines the MIDI subsystem that will be used. There are additional settings for
the MIDI subsystems used. For a full list of available <strong>midi driver settings</strong>, please refer to <a href="fluidsettings.xml" target="_blank"><strong>FluidSettings Documentation</strong></a>.
\section MIDIPlayer Loading and Playing a MIDI file
FluidSynth can be used to play MIDI files, using the MIDI File Player interface. It follows a high level implementation, though its implementation is currently incomplete. After initializing the synthesizer, create the player passing the synth instance to new_fluid_player(). Then, you can add some SMF file names to the player using fluid_player_add(), and finally call fluid_player_play() to start the playback. You can check if the player has finished by calling fluid_player_get_status(), or wait for the player to terminate using fluid_player_join().
\code
#include <fluidsynth.h>
int main(int argc, char** argv)
{
int i;
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_player_t* player;
fluid_audio_driver_t* adriver;
settings = new_fluid_settings();
synth = new_fluid_synth(settings);
player = new_fluid_player(synth);
/* process command line arguments */
for (i = 1; i < argc; i++) {
if (fluid_is_soundfont(argv[i])) {
fluid_synth_sfload(synth, argv[1], 1);
}
if (fluid_is_midifile(argv[i])) {
fluid_player_add(player, argv[i]);
}
}
/* start the synthesizer thread */
adriver = new_fluid_audio_driver(settings, synth);
/* play the midi files, if any */
fluid_player_play(player);
/* wait for playback termination */
fluid_player_join(player);
/* cleanup */
delete_fluid_audio_driver(adriver);
delete_fluid_player(player);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return 0;
}
\endcode
A list of available <strong>MIDI player settings</strong> can be found in <a href="fluidsettings.xml" target="_blank"><b>FluidSettings Documentation</b></a>.
\section FileRenderer Fast file renderer for non-realtime MIDI file rendering
Instead of creating an audio driver as described in section \ref MIDIPlayer one may chose to use the file renderer, which is the fastest way to synthesize MIDI files.
\code
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_player_t* player;
fluid_file_renderer_t* renderer;
settings = new_fluid_settings();
// specify the file to store the audio to
// make sure you compiled fluidsynth with libsndfile to get a real wave file
// otherwise this file will only contain raw s16 stereo PCM
fluid_settings_setstr(settings, "audio.file.name", "/path/to/output.wav");
// use number of samples processed as timing source, rather than the system timer
fluid_settings_setstr(settings, "player.timing-source", "sample");
// since this is a non-realtime scenario, there is no need to pin the sample data
fluid_settings_setint(settings, "synth.lock-memory", 0);
synth = new_fluid_synth(settings);
// *** loading of a soundfont omitted ***
player = new_fluid_player(synth);
fluid_player_add(player, "/path/to/midifile.mid");
fluid_player_play(player);
renderer = new_fluid_file_renderer (synth);
while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING)
{
if (fluid_file_renderer_process_block(renderer) != FLUID_OK)
{
break;
}
}
// just for sure: stop the playback explicitly and wait until finished
fluid_player_stop(player);
fluid_player_join(player);
delete_fluid_file_renderer(renderer);
delete_fluid_player(player);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
\endcode
Various output files types are supported, if compiled with libsndfile. Those can be specified via the \c settings object as well. Refer to the <a href="fluidsettings.xml#audio.file.endian" target="_blank"><b>FluidSettings Documentation</b></a> for more \c audio.file\.\* options.
\section MIDIPlayerMem Playing a MIDI file from memory
FluidSynth can be also play MIDI files directly from a buffer in memory. If you need to play a file from a stream (such as stdin, a network, or a high-level file interface), you can load the entire file into a buffer first, and then use this approach. Use the same technique as above, but rather than calling fluid_player_add(), load it into memory and call fluid_player_add_mem() instead. Once you have passed a buffer to fluid_player_add_mem(), it is copied, so you may use it again or free it immediately (it is your responsibility to free it if you allocated it).
\code
#include <stdlib.h>
#include <string.h>
#include <fluidsynth.h>
/* An example midi file */
const char MIDIFILE[] = {
0x4d, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06,
0x00, 0x01, 0x00, 0x01, 0x01, 0xe0, 0x4d, 0x54,
0x72, 0x6b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x90,
0x3c, 0x64, 0x87, 0x40, 0x80, 0x3c, 0x7f, 0x00,
0x90, 0x43, 0x64, 0x87, 0x40, 0x80, 0x43, 0x7f,
0x00, 0x90, 0x48, 0x64, 0x87, 0x40, 0x80, 0x48,
0x7f, 0x83, 0x60, 0xff, 0x2f, 0x00
};
int main(int argc, char** argv)
{
int i;
void* buffer;
size_t buffer_len;
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_player_t* player;
fluid_audio_driver_t* adriver;
settings = new_fluid_settings();
synth = new_fluid_synth(settings);
player = new_fluid_player(synth);
adriver = new_fluid_audio_driver(settings, synth);
/* process command line arguments */
for (i = 1; i < argc; i++) {
if (fluid_is_soundfont(argv[i])) {
fluid_synth_sfload(synth, argv[1], 1);
}
}
/* queue up the in-memory midi file */
fluid_player_add_mem(player, MIDIFILE, sizeof(MIDIFILE));
/* play the midi file */
fluid_player_play(player);
/* wait for playback termination */
fluid_player_join(player);
/* cleanup */
delete_fluid_audio_driver(adriver);
delete_fluid_player(player);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return 0;
}
\endcode
\section MIDIRouter Real-time MIDI router
The MIDI router is one more processing layer directly behind the MIDI input. It processes incoming MIDI events and generates control events for the synth. It can be used to filter or modify events prior to sending them to the synthesizer. When created, the MIDI router is transparent and simply passes all MIDI events. Router "rules" must be added to actually make use of its capabilities.
Some examples of MIDI router usage:
- Filter messages (Example: Pass sustain pedal CCs only to selected channels)
- Split the keyboard (Example: noteon with notenr < x: to ch 1, >x to ch 2)
- Layer sounds (Example: for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...)
- Velocity scaling (Example: for each noteon event, scale the velocity by 1.27)
- Velocity switching (Example: v <= 100: "Angel Choir"; v > 100: "Hell's Bells")
- Get rid of aftertouch
The MIDI driver API has a clean separation between the midi thread and the synthesizer. That opens the door to add a midi router module.
MIDI events coming from the MIDI player do not pass through the MIDI router.
\code
#include <fluidsynth.h>
int main(int argc, char** argv)
{
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_midi_router_t* router;
fluid_midi_router_rule_t* rule;
settings = new_fluid_settings();
synth = new_fluid_synth(settings);
/* Create the MIDI router and pass events to the synthesizer */
router = new_fluid_midi_router (settings, fluid_synth_handle_midi_event, synth);
/* Clear default rules */
fluid_midi_router_clear_rules (router);
/* Add rule to map all notes < MIDI note #60 on any channel to channel 4 */
rule = new_fluid_midi_router_rule ();
fluid_midi_router_rule_set_chan (rule, 0, 15, 0.0, 4); /* Map all to channel 4 */
fluid_midi_router_rule_set_param1 (rule, 0, 59, 1.0, 0); /* Match notes < 60 */
fluid_midi_router_add_rule (router, rule, FLUID_MIDI_ROUTER_RULE_NOTE);
/* Add rule to map all notes >= MIDI note #60 on any channel to channel 5 */
rule = new_fluid_midi_router_rule ();
fluid_midi_router_rule_set_chan (rule, 0, 15, 0.0, 5); /* Map all to channel 5 */
fluid_midi_router_rule_set_param1 (rule, 60, 127, 1.0, 0); /* Match notes >= 60 */
fluid_midi_router_add_rule (router, rule, FLUID_MIDI_ROUTER_RULE_NOTE);
/* Add rule to reverse direction of pitch bender on channel 7 */
rule = new_fluid_midi_router_rule ();
fluid_midi_router_rule_set_chan (rule, 7, 7, 1.0, 0); /* Match channel 7 only */
fluid_midi_router_rule_set_param1 (rule, 0, 16383, -1.0, 16383); /* Reverse pitch bender */
fluid_midi_router_add_rule (router, rule, FLUID_MIDI_ROUTER_RULE_PITCH_BEND);
/* ... Create audio driver, process events, etc ... */
/* cleanup */
delete_fluid_midi_router(router);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return 0;
}
\endcode
\section Sequencer
FluidSynth's 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.
The client program should first initialize the sequencer instance using the function new_fluid_sequencer2(). There is a complementary function delete_fluid_sequencer() to delete it. After creating the sequencer instance, the destinations can be registered using fluid_sequencer_register_fluidsynth() for the synthesizer destination, and optionally using fluid_sequencer_register_client() for the client destination providing a suitable callback function. It can be unregistered using fluid_sequencer_unregister_client(). After the initialization, events can be sent with fluid_sequencer_send_now() and scheduled to the future with fluid_sequencer_send_at(). The registration functions return identifiers, that can be used as destinations of an event using fluid_event_set_dest().
The function fluid_sequencer_get_tick() returns the current playing position. A program may choose a new timescale in milliseconds using fluid_sequencer_set_time_scale().
The following example uses the fluidsynth sequencer to implement a sort of music box. FluidSynth internal clock is used to schedule repetitive sequences of notes. The next sequence is scheduled on advance before the end of the current one, using a timer event that triggers a callback function. The scheduling times are always absolute values, to avoid slippage.
\code
#include "fluidsynth.h"
fluid_synth_t* synth;
fluid_audio_driver_t* adriver;
fluid_sequencer_t* sequencer;
short synthSeqID, mySeqID;
unsigned int now;
unsigned int seqduration;
// prototype
void seq_callback(unsigned int time, fluid_event_t* event, fluid_sequencer_t* seq, void* data);
void createsynth()
{
fluid_settings_t* settings;
settings = new_fluid_settings();
fluid_settings_setint(settings, "synth.reverb.active", 0);
fluid_settings_setint(settings, "synth.chorus.active", 0);
synth = new_fluid_synth(settings);
adriver = new_fluid_audio_driver(settings, synth);
sequencer = new_fluid_sequencer2(0);
// register synth as first destination
synthSeqID = fluid_sequencer_register_fluidsynth(sequencer, synth);
// register myself as second destination
mySeqID = fluid_sequencer_register_client(sequencer, "me", seq_callback, NULL);
// the sequence duration, in ms
seqduration = 1000;
}
void deletesynth()
{
delete_fluid_sequencer(sequencer);
delete_fluid_audio_driver(adriver);
delete_fluid_synth(synth);
}
void loadsoundfont()
{
int fluid_res;
// put your own path here
fluid_res = fluid_synth_sfload(synth, "Inside:VintageDreamsWaves-v2.sf2", 1);
}
void sendnoteon(int chan, short key, unsigned int date)
{
int fluid_res;
fluid_event_t *evt = new_fluid_event();
fluid_event_set_source(evt, -1);
fluid_event_set_dest(evt, synthSeqID);
fluid_event_noteon(evt, chan, key, 127);
fluid_res = fluid_sequencer_send_at(sequencer, evt, date, 1);
delete_fluid_event(evt);
}
void schedule_next_callback()
{
int fluid_res;
// I want to be called back before the end of the next sequence
unsigned int callbackdate = now + seqduration/2;
fluid_event_t *evt = new_fluid_event();
fluid_event_set_source(evt, -1);
fluid_event_set_dest(evt, mySeqID);
fluid_event_timer(evt, NULL);
fluid_res = fluid_sequencer_send_at(sequencer, evt, callbackdate, 1);
delete_fluid_event(evt);
}
void schedule_next_sequence() {
// Called more or less before each sequence start
// the next sequence start date
now = now + seqduration;
// the sequence to play
// the beat : 2 beats per sequence
sendnoteon(0, 60, now + seqduration/2);
sendnoteon(0, 60, now + seqduration);
// melody
sendnoteon(1, 45, now + seqduration/10);
sendnoteon(1, 50, now + 4*seqduration/10);
sendnoteon(1, 55, now + 8*seqduration/10);
// so that we are called back early enough to schedule the next sequence
schedule_next_callback();
}
/* sequencer callback */
void seq_callback(unsigned int time, fluid_event_t* event, fluid_sequencer_t* seq, void* data) {
schedule_next_sequence();
}
int main(void) {
createsynth();
loadsoundfont();
// initialize our absolute date
now = fluid_sequencer_get_tick(sequencer);
schedule_next_sequence();
sleep(100000);
deletesynth();
return 0;
}
\endcode
\section Shell Shell interface
The shell interface allows you to send simple textual commands to the synthesizer, to parse a command file, or to read commands from the stdin or other input streams. To find the list of currently supported commands, type @c help in the fluidsynth command line shell. For a full list of available <strong>command line settings</strong>, please refer to <a href="fluidsettings.xml#shell.prompt" target="_blank"><b>FluidSettings Documentation</b></a>.
\section Multi-channel Multi-Channel audio rendering
FluidSynth is capable of rendering all audio and all effects from all MIDI channels to separate stereo buffers. Refer to the documentation of fluid_synth_process() and review the different use-cases in the example file for information on how to do that: \ref fluidsynth_process.c
The following chart illustrates how the voices (produced by MIDI NoteOns) are dispatched or mapped to their dry/effects audio buffers.
\htmlonly
<a href="FluidMixer.pdf">
<img src="FluidMixer.jpg" alt="FluidSynth Mixer Chart">
</a>
\endhtmlonly
\section synth-context Understanding the "synthesis context"
When reading through the functions exposed via our API, you will often read the note: "May or may not be called from synthesis context."
The reason for this is that some functions are intentionally not thread-safe. Or they require to be called from this context to behave correctly.
FluidSynth's rendering engine is implemented by using the "Dispatcher Thread Pattern". This means that a certain thread @c A which calls one of FluidSynth's rendering functions, namely
- fluid_synth_process()
- fluid_synth_nwrite_float()
- fluid_synth_write_float()
- fluid_synth_write_s16()
automatically becomes the "synthesis thread". The terms "synthesis context" and "synthesis thread" are equivalent. A few locations in our API provide hooks that allow you to interfere this "synthesis context". At those locations you can register your own custom functions that will always be called by thread @c A. For this use-case, the following functions are of interest:
- new_fluid_audio_driver2()
- fluid_player_set_playback_callback()
- fluid_sequencer_register_client()
\section Advanced Advanced features, not yet documented. API reference may contain more info.
- Accessing low-level voice parameters
- Reverb settings
- Chorus settings
- Interpolation settings (set_gen, get_gen, NRPN)
- Voice overflow settings
- LADSPA effects unit
- MIDI tunings
*/
/*!

2174
doc/images/fluid_mixer.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 150 KiB

148
doc/recent_changes.txt Normal file
View file

@ -0,0 +1,148 @@
/*!
\page RecentChanges Recent Changes
\section NewIn2_2_0 What's new in 2.2.0?
- #fluid_file_callbacks_t now uses <code>long long</code> as file-offset type (see #fluid_long_long_t). This is a breaking change, which allows to load SoundFonts bigger than 2GiB on Windows. This change required to bump fluidsynth's SOVERSION.
- fluid_event_any_control_change() has been removed
- various fluid_event_*() functions that received a "value" argument of type <code>short</code> now receive an <code>int</code> argument in preparation for MIDI 2.0 support
- The sequencer has received a major revisal. For you that means:
- The sequencer's queue no longer blocks the synthesizer thread, due to being busy arranging its events internally.
- Events that share the same tick was given a new, documented order, see fluid_sequencer_send_at().
- The sequencer's scale can now be used for arbitrary tempo changes. Previously, the scale of the sequencer was limited to 1000. The only limitation now is >0.
- The dynamic-sample-loader has learned support to pin samples, see fluid_synth_pin_preset() and fluid_synth_unpin_preset()
\section NewIn2_1_4 What's new in 2.1.4?
- a regression introduced in 2.1.3 broke fluid_synth_start() for DLS presets
\section NewIn2_1_1 What's new in 2.1.1?
- requirements for explicit sequencer client unregistering have been relaxed: delete_fluid_sequencer() now correctly frees any registered sequencer clients (clients can still be explicitly unregistered)
- using the sequencer with the system timer as timing source has been deprecated
\section NewIn2_1_0 What's new in 2.1.0?
- <span style="color:red">refrain from using fluid_synth_set_sample_rate()</span>
- \setting{synth_sample-rate} is no real-time setting anymore, see note about fluid_synth_set_sample_rate()
- new reverb engine
- chorus is now stereophonic
- smallest allowed chorus speed is now 0.1 Hz (previously 0.29 Hz)
- the following audio drivers were added:
- opensles
- oboe
- sdl2
- waveout
\section NewIn2_0_8 What's new in 2.0.8?
- fluid_sample_set_sound_data() caused broken sound when copying sample data
\section NewIn2_0_7 What's new in 2.0.7?
- fluid_free() has been added to allow proper deallocation by programming languages other than C/C++
\section NewIn2_0_6 What's new in 2.0.6?
- the MIDI player did not emit any audio when calling fluid_player_play() after fluid_player_stop()
\section NewIn2_0_5 What's new in 2.0.5?
- fluid_synth_process() omitted audio samples when called with arbitrary sample counts that were not a multiple of fluid_synth_get_internal_bufsize()
- fluid_synth_sfunload() was not releasing sample buffers of SoundFont3 files if \setting{synth_dynamic-sample-loading} was set to FALSE
\section NewIn2_0_3 What's new in 2.0.3?
- fix incorrect behaviour of fluid_sample_set_sound_data()
- add missing getters for midi events:
- fluid_midi_event_get_text()
- fluid_midi_event_get_lyrics()
\section NewIn2_0_2 What's new in 2.0.2?
- fluid_synth_error() has been deprecated, use fluid_set_log_function() to interfere log messages
\section NewIn2_0_0 What's new in 2.0.0?
FluidSynths major version was bumped. The API was reworked, deprecated functions were removed.
<strong><span style="color:red">Important changes that may not result in a compilation error but may cause your app to misbehave:</span></strong>
- all public \c fluid_settings_* functions that return an integer which is not meant to be interpreted as bool consistently return either FLUID_OK or FLUID_FAILED
- fluid_settings_setstr() cannot be used to set integer (toggle) settings with "yes" or "no" values anymore. Use fluid_settings_setint() instead, for example: <br /><code>fluid_settings_setint(settings, "synth.reverb.active", 0)</code> instead of <code>fluid_settings_setstr(settings, "synth.reverb.active", "no")</code>
- <span style="text-decoration:line-through;">explicit client unregistering is required for fluid_sequencer_register_client() and fluid_sequencer_register_fluidsynth()</span> (since fluidsynth 2.1.1 not required anymore, but still recommend)
- all public functions consistently receive signed integers for soundfont ids, bank and program numbers
- use unique device names for the \setting{audio_portaudio_device} setting
- fluid_synth_process() received a new more flexible implementation, but now requires zeroed-out sample buffers
<strong>Other changes in FluidSynth 2.0.0 concerning developers:</strong>
- all public \c delete_* functions return void and are safe when called with NULL
- the shell command handler was decoupled internally, as a consequence the param list of new_fluid_server() and new_fluid_cmd_handler() was adapted
- \c fluid_settings_set* functions no longer silently register unknown settings but return an error instead
- reverb: roomsize is now limited to an upper threshold of 1.0 to avoid exponential volume increase
- rename \c fluid_mod_new() and \c fluid_mod_delete() to match naming conventions: new_fluid_mod() and delete_fluid_mod()
- rename chorus getters to match naming conventions: fluid_synth_get_chorus_speed() and fluid_synth_get_chorus_depth()
- fluid_synth_remove_sfont() returns FLUID_OK or FLUID_FAILED
- introduce a separate data type for sequencer client IDs: #fluid_seq_id_t
- fluid_get_userconf() has been implemented for Windows
<strong>New Features and API additions:</strong>
- add \setting{midi_autoconnect} a setting for automatically connecting fluidsynth to available MIDI input ports
- add \setting{synth_overflow_important} and \setting{synth_overflow_important-channels} settings to take midi channels during overflow calculation into account that are considered to be "important"
- add \setting{synth_dynamic-sample-loading} a setting for enabling on demand sample loading
- add support for polyphonic key pressure events, see fluid_event_key_pressure() and fluid_synth_key_pressure()
- add fluid_synth_add_default_mod() and fluid_synth_remove_default_mod() for manipulating default modulators
- add individual reverb setters: fluid_synth_set_reverb_roomsize(), fluid_synth_set_reverb_damp(), fluid_synth_set_reverb_width(), fluid_synth_set_reverb_level()
- add individual chorus setters: fluid_synth_set_chorus_nr(), fluid_synth_set_chorus_level(), fluid_synth_set_chorus_speed(), fluid_synth_set_chorus_depth(), fluid_synth_set_chorus_type()
- add realtime settings for \setting{synth_reverb_damp} and \setting{synth_chorus_depth} parameters
- add seek support to midi-player, see fluid_player_seek()
- expose functions to manipulate the ladspa effects unit (see ladspa.h)
- add support for text and lyrics midi events, see fluid_midi_event_set_lyrics() and fluid_midi_event_set_text()
- complete rewrite of the soundfont loader API, see sfont.h
- support for 24 bit audio samples, see fluid_sample_set_sound_data()
- expose new_fluid_defsfloader() to support loading soundfonts from memory, see fluid_sfloader_set_callbacks() and <a href="fluidsynth_sfload_mem_8c-example.html">fluidsynth_sfload_mem.c</a>
- remove these structs from the public API and provide proper getter and setter functions instead:
- struct _fluid_sfloader_t
- struct _fluid_sample_t
- struct _fluid_sfont_t
- struct _fluid_preset_t
- add an additional general-purpose IIR filter, see fluid_synth_set_custom_filter()
- add a custom sinusoidal modulator mapping function, see #FLUID_MOD_SIN
- implement polymono support according to MIDI specs:
- add basic channel support, see fluid_synth_reset_basic_channel(), fluid_synth_set_basic_channel(), fluid_synth_get_basic_channel()
- implement MIDI modes Omni On, Omni Off, Poly, Mono, see #fluid_basic_channel_modes
- implement portamento control, see fluid_synth_set_portamento_mode(), fluid_synth_get_portamento_mode()
- implement legato control, see fluid_synth_set_legato_mode(), fluid_synth_get_legato_mode()
- implement breath control, see fluid_synth_set_breath_mode(), fluid_synth_get_breath_mode()
<strong>API cleanups:</strong>
- the ramsfont has been removed, because it is unmaintained and believed to be unused; please get in touch with the mailing list if you still need it
- remove deprecated fluid_synth_get_channel_info() in favour of fluid_synth_get_program() and fluid_synth_get_channel_preset()
- remove deprecated fluid_settings_getstr()
- remove deprecated fluid_synth_set_midi_router(), instead supply the midi-router instance when creating a command handler with new_fluid_cmd_handler()
- remove deprecated fluid_get_hinstance() and fluid_set_hinstance() (dsound driver now uses the desktop window)
- remove deprecated fluid_synth_create_key_tuning(), use fluid_synth_activate_key_tuning(synth, bank, prog, name, pitch, FALSE) instead
- remove deprecated fluid_synth_create_octave_tuning(), use fluid_synth_activate_octave_tuning(synth, bank, prog, name, pitch, FALSE) instead
- remove deprecated fluid_synth_select_tuning(), use fluid_synth_activate_tuning(synth, chan, bank, prog, FALSE) instead
- remove deprecated fluid_synth_reset_tuning(), use fluid_synth_deactivate_tuning(synth, chan, FALSE) instead
- remove deprecated FLUID_HINT_INTEGER
- remove deprecated fluid_synth_set_gen2() as there doesn't seem to be a use case for absolute generator values
- remove deprecated "synth.parallel-render" setting
- remove obsolete "audio.[out|in]put-channels" settings
- remove unimplemented "synth.dump" setting
- remove fluid_cmd_handler_register() and fluid_cmd_handler_unregister() from public API, as they seem to be unused downstream
- remove misspelled FLUID_SEQ_PITCHWHHELSENS macro
- remove struct _fluid_mod_t from public API, use the getters and setters of mod.h instead
- remove struct _fluid_gen_t, fluid_gen_set_default_values() and enum fluid_gen_flags from public API
- remove macros fluid_sfont_get_id() and fluid_sample_refcount() from public API
- remove FLUID_NUM_MOD macro from public API
- remove the following deprecated enum values from public API:
- GEN_LAST
- LAST_LOG_LEVEL
- FLUID_SEQ_LASTEVENT
- FLUID_MIDI_ROUTER_RULE_COUNT
*/

21
doc/usage/_overview.txt Normal file
View file

@ -0,0 +1,21 @@
/*!
\page UsageGuide Usage Guide
- \subpage CreatingSettings
- \subpage CreatingSynth
- \subpage LoadingSoundfonts
- \subpage CreatingAudioDriver
- \subpage UsingSynth
- \subpage SendingMIDI
- \subpage RealtimeMIDI
- \subpage MIDIPlayer
- \subpage FileRenderer
- \subpage MIDIPlayerMem
- \subpage MIDIRouter
- \subpage Sequencer
- \subpage Shell
- \subpage Multi-channel
- \subpage synth-context
- \subpage Advanced
*/

16
doc/usage/advanced.txt Normal file
View file

@ -0,0 +1,16 @@
/*!
\page Advanced Advanced features
The following features are not yet fully documented. Some information can be
found in the API reference and in the GitHub Wiki.
- Accessing low-level voice parameters
- Reverb settings
- Chorus settings
- Interpolation settings (set_gen, get_gen, NRPN)
- Voice overflow settings
- LADSPA effects unit
- MIDI tunings
*/

View file

@ -0,0 +1,82 @@
/*!
\page CreatingAudioDriver Creating the audio driver
The synthesizer itself does not write any audio to the audio output. This
allows application developers to manage the audio output themselves if they
wish. The next section describes the use of the synthesizer without an audio
driver in more detail.
Creating the audio driver is straightforward: set the
<code>audio.driver</code> settings and create the driver object. Because the
FluidSynth has support for several audio systems, you may want to change
which one you want to use. The list below shows the audio systems that are
currently supported. It displays the name, as used by the fluidsynth library,
and a description.
- jack: JACK Audio Connection Kit (Linux, Mac OS X, Windows)
- alsa: Advanced Linux Sound Architecture (Linux)
- oss: Open Sound System (Linux, Unix)
- pulseaudio: PulseAudio (Linux, Mac OS X, Windows)
- coreaudio: Apple CoreAudio (Mac OS X)
- dsound: Microsoft DirectSound (Windows)
- portaudio: PortAudio Library (Mac OS 9 & X, Windows, Linux)
- sndman: Apple SoundManager (Mac OS Classic)
- dart: DART sound driver (OS/2)
- opensles: OpenSL ES (Android)
- oboe: Oboe (Android)
- waveout: Microsoft WaveOut, alternative to DirectSound (Windows CE x86,
Windows Mobile 2003 for ARMv5, Windows 98 SE, Windows NT 4.0, Windows XP
and later)
- file: Driver to output audio to a file
- sdl2*: Simple DirectMedia Layer (Linux, Windows, Mac OS X, iOS, Android,
FreeBSD, Haiku, etc.)
The default audio driver depends on the settings with which FluidSynth was
compiled. You can get the default driver with
fluid_settings_getstr_default(). To get the list of available drivers use the
fluid_settings_foreach_option() function. Finally, you can set the driver
with fluid_settings_setstr(). In most cases, the default driver should work
out of the box.
Additional options that define the audio quality and latency are
\setting{audio_sample-format}, \setting{audio_period-size}, and
\setting{audio_periods}. The details are described later.
You create the audio driver with the new_fluid_audio_driver() function. This
function takes the settings and synthesizer object as arguments. For example:
\code
void init()
{
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_audio_driver_t* adriver;
settings = new_fluid_settings();
/* Set the synthesizer settings, if necessary */
synth = new_fluid_synth(settings);
fluid_settings_setstr(settings, "audio.driver", "jack");
adriver = new_fluid_audio_driver(settings, synth);
}
\endcode
As soon as the audio driver is created, it will start playing. The audio
driver creates a separate thread that uses the synthesizer object to generate
the audio.
There are a number of general audio driver settings. The audio.driver settings
define the audio subsystem that will be used. The \setting{audio_periods} and
\setting{audio_period-size} settings define the latency and robustness against
scheduling delays. There are additional settings for the audio subsystems used.
For a full list of available <strong>audio driver settings</strong>, please
refer to the \setting{audio} documentation.
<strong>*Note:</strong> In order to use sdl2 as audio driver, the application
is responsible for initializing SDL (e.g. with SDL_Init()). This must be done
<strong>before</strong> the first call to <code>new_fluid_settings()</code>!
Also make sure to call SDL_Quit() after all fluidsynth instances have been
destroyed.
*/

View file

@ -0,0 +1,38 @@
/*!
\page CreatingSettings Creating and changing the settings
Before you can use the synthesizer, you have to create a settings object. The
settings objects is used by many components of the FluidSynth library. It gives
a unified API to set the parameters of the audio drivers, the midi drivers, the
synthesizer, and so forth. A number of default settings are defined by the
current implementation.
All settings have a name that follows the "dotted-name" notation. For example,
\setting{synth_polyphony} refers to the number of voices (polyphony) allocated
by the synthesizer. The settings also have a type. There are currently three
types: strings, numbers (double floats), and integers. You can change the
values of a setting using the fluid_settings_setstr(), fluid_settings_setnum(),
and fluid_settings_setint() functions. For example:
\code
#include <fluidsynth.h>
int main(int argc, char** argv)
{
fluid_settings_t* settings = new_fluid_settings();
fluid_settings_setint(settings, "synth.polyphony", 128);
/* ... */
delete_fluid_settings(settings);
return 0;
}
\endcode
The API contains the functions to query the type, the current value, the
default value, the range and the "hints" of a setting. The range is the minimum
and maximum value of the setting. The hints gives additional information about
a setting. For example, whether a string represents a filename. Or whether a
number should be interpreted on on a logarithmic scale. Check the settings.h
API documentation for a description of all functions.
*/

View file

@ -0,0 +1,29 @@
/*!
\page CreatingSynth Creating the synthesizer
To create the synthesizer, you pass it the settings object, as in the
following example:
\code
#include <fluidsynth.h>
int main(int argc, char** argv)
{
fluid_settings_t* settings;
fluid_synth_t* synth;
settings = new_fluid_settings();
synth = new_fluid_synth(settings);
/* Do useful things here */
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return 0;
}
\endcode
For a full list of available <strong>synthesizer settings</strong>, please
refer to the \setting{synth} documentation.
*/

View file

@ -0,0 +1,60 @@
/*!
\page FileRenderer Fast file renderer for non-realtime MIDI file rendering
Instead of creating an audio driver as described in section \ref MIDIPlayer
one may chose to use the file renderer, which is the fastest way to
synthesize MIDI files.
\code
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_player_t* player;
fluid_file_renderer_t* renderer;
settings = new_fluid_settings();
// specify the file to store the audio to
// make sure you compiled fluidsynth with libsndfile to get a real wave file
// otherwise this file will only contain raw s16 stereo PCM
fluid_settings_setstr(settings, "audio.file.name", "/path/to/output.wav");
// use number of samples processed as timing source, rather than the system timer
fluid_settings_setstr(settings, "player.timing-source", "sample");
// since this is a non-realtime scenario, there is no need to pin the sample data
fluid_settings_setint(settings, "synth.lock-memory", 0);
synth = new_fluid_synth(settings);
// *** loading of a soundfont omitted ***
player = new_fluid_player(synth);
fluid_player_add(player, "/path/to/midifile.mid");
fluid_player_play(player);
renderer = new_fluid_file_renderer (synth);
while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING)
{
if (fluid_file_renderer_process_block(renderer) != FLUID_OK)
{
break;
}
}
// just for sure: stop the playback explicitly and wait until finished
fluid_player_stop(player);
fluid_player_join(player);
delete_fluid_file_renderer(renderer);
delete_fluid_player(player);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
\endcode
Various output files types are supported, if compiled with libsndfile. Those
can be specified via the \c settings object as well. Refer to the
\setting{audio} documentation for more \c audio.file\.\* options.
*/

View file

@ -0,0 +1,34 @@
/*!
\page LoadingSoundfonts Loading and managing SoundFonts
Before any sound can be produced, the synthesizer needs a SoundFont.
SoundFonts are loaded with the fluid_synth_sfload() function. The function
takes the path to a SoundFont file and a boolean to indicate whether the
presets of the MIDI channels should be updated after the SoundFont is loaded.
When the boolean value is TRUE, all MIDI channel bank and program numbers
will be refreshed, which may cause new instruments to be selected from the
newly loaded SoundFont.
The synthesizer can load any number of SoundFonts. The loaded SoundFonts are
treated as a stack, where each new loaded SoundFont is placed at the top of
the stack. When selecting presets by bank and program numbers, SoundFonts are
searched beginning at the top of the stack. In the case where there are
presets in different SoundFonts with identical bank and program numbers, the
preset from the most recently loaded SoundFont is used. The
fluid_synth_program_select() can be used for unambiguously selecting a preset
or bank offsets could be applied to each SoundFont with
fluid_synth_set_bank_offset(), to try and ensure that each preset has unique
bank and program numbers.
The fluid_synth_sfload() function returns the unique identifier of the loaded
SoundFont, or -1 in case of an error. This identifier is used in subsequent
management functions: fluid_synth_sfunload() removes the SoundFont,
fluid_synth_sfreload() reloads the SoundFont. When a SoundFont is reloaded,
it retains it's ID and position on the SoundFont stack.
Additional API functions are provided to get the number of loaded SoundFonts
and to get a pointer to the SoundFont.
*/

View file

@ -0,0 +1,17 @@
/*!
\page UsingSynth Using the synthesizer without an audio driver
It is possible to use the synthesizer object without creating an audio
driver. This is desirable if the application using FluidSynth manages the
audio output itself. The synthesizer has several API functions that can be
used to obtain the audio output:
fluid_synth_write_s16() fills two buffers (left and right channel) with
samples coded as signed 16 bits (the endian-ness is machine dependent).
fluid_synth_write_float() fills a left and right audio buffer with 32 bits
floating point samples. The function fluid_synth_process() is the generic
interface for synthesizing audio, which is also capable of multi channel
audio output.
*/

55
doc/usage/midi_player.txt Normal file
View file

@ -0,0 +1,55 @@
/*!
\page MIDIPlayer Loading and playing a MIDI file
FluidSynth can be used to play MIDI files, using the MIDI File Player
interface. It follows a high level implementation, though its implementation
is currently incomplete. After initializing the synthesizer, create the
player passing the synth instance to new_fluid_player(). Then, you can add
some SMF file names to the player using fluid_player_add(), and finally call
fluid_player_play() to start the playback. You can check if the player has
finished by calling fluid_player_get_status(), or wait for the player to
terminate using fluid_player_join().
\code
#include <fluidsynth.h>
int main(int argc, char** argv)
{
int i;
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_player_t* player;
fluid_audio_driver_t* adriver;
settings = new_fluid_settings();
synth = new_fluid_synth(settings);
player = new_fluid_player(synth);
/* process command line arguments */
for (i = 1; i < argc; i++) {
if (fluid_is_soundfont(argv[i])) {
fluid_synth_sfload(synth, argv[1], 1);
}
if (fluid_is_midifile(argv[i])) {
fluid_player_add(player, argv[i]);
}
}
/* start the synthesizer thread */
adriver = new_fluid_audio_driver(settings, synth);
/* play the midi files, if any */
fluid_player_play(player);
/* wait for playback termination */
fluid_player_join(player);
/* cleanup */
delete_fluid_audio_driver(adriver);
delete_fluid_player(player);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return 0;
}
\endcode
A list of available <strong>MIDI player settings</strong> can be found in the
\setting{player} documentation.
*/

View file

@ -0,0 +1,64 @@
/*!
\page MIDIPlayerMem Playing a MIDI file from memory
FluidSynth can be also play MIDI files directly from a buffer in memory. If
you need to play a file from a stream (such as stdin, a network, or a
high-level file interface), you can load the entire file into a buffer first,
and then use this approach. Use the same technique as above, but rather than
calling fluid_player_add(), load it into memory and call
fluid_player_add_mem() instead. Once you have passed a buffer to
fluid_player_add_mem(), it is copied, so you may use it again or free it
immediately (it is your responsibility to free it if you allocated it).
\code
#include <stdlib.h>
#include <string.h>
#include <fluidsynth.h>
/* An example midi file */
const char MIDIFILE[] = {
0x4d, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06,
0x00, 0x01, 0x00, 0x01, 0x01, 0xe0, 0x4d, 0x54,
0x72, 0x6b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x90,
0x3c, 0x64, 0x87, 0x40, 0x80, 0x3c, 0x7f, 0x00,
0x90, 0x43, 0x64, 0x87, 0x40, 0x80, 0x43, 0x7f,
0x00, 0x90, 0x48, 0x64, 0x87, 0x40, 0x80, 0x48,
0x7f, 0x83, 0x60, 0xff, 0x2f, 0x00
};
int main(int argc, char** argv)
{
int i;
void* buffer;
size_t buffer_len;
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_player_t* player;
fluid_audio_driver_t* adriver;
settings = new_fluid_settings();
synth = new_fluid_synth(settings);
player = new_fluid_player(synth);
adriver = new_fluid_audio_driver(settings, synth);
/* process command line arguments */
for (i = 1; i < argc; i++) {
if (fluid_is_soundfont(argv[i])) {
fluid_synth_sfload(synth, argv[1], 1);
}
}
/* queue up the in-memory midi file */
fluid_player_add_mem(player, MIDIFILE, sizeof(MIDIFILE));
/* play the midi file */
fluid_player_play(player);
/* wait for playback termination */
fluid_player_join(player);
/* cleanup */
delete_fluid_audio_driver(adriver);
delete_fluid_player(player);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return 0;
}
\endcode
*/

76
doc/usage/midi_router.txt Normal file
View file

@ -0,0 +1,76 @@
/*!
\page MIDIRouter Real-time MIDI router
The MIDI router is one more processing layer directly behind the MIDI input.
It processes incoming MIDI events and generates control events for the synth.
It can be used to filter or modify events prior to sending them to the
synthesizer. When created, the MIDI router is transparent and simply passes
all MIDI events. Router "rules" must be added to actually make use of its
capabilities.
Some examples of MIDI router usage:
- Filter messages (Example: Pass sustain pedal CCs only to selected channels)
- Split the keyboard (Example: noteon with notenr < x: to ch 1, >x to ch 2)
- Layer sounds (Example: for each noteon received on ch 1, create a noteon on
ch1, ch2, ch3,...)
- Velocity scaling (Example: for each noteon event, scale the velocity by
1.27)
- Velocity switching (Example: v <= 100: "Angel Choir"; v > 100: "Hell's
Bells")
- Get rid of aftertouch
The MIDI driver API has a clean separation between the midi thread and the
synthesizer. That opens the door to add a midi router module.
MIDI events coming from the MIDI player do not pass through the MIDI router.
\code
#include <fluidsynth.h>
int main(int argc, char** argv)
{
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_midi_router_t* router;
fluid_midi_router_rule_t* rule;
settings = new_fluid_settings();
synth = new_fluid_synth(settings);
/* Create the MIDI router and pass events to the synthesizer */
router = new_fluid_midi_router (settings, fluid_synth_handle_midi_event, synth);
/* Clear default rules */
fluid_midi_router_clear_rules (router);
/* Add rule to map all notes < MIDI note #60 on any channel to channel 4 */
rule = new_fluid_midi_router_rule ();
fluid_midi_router_rule_set_chan (rule, 0, 15, 0.0, 4); /* Map all to channel 4 */
fluid_midi_router_rule_set_param1 (rule, 0, 59, 1.0, 0); /* Match notes < 60 */
fluid_midi_router_add_rule (router, rule, FLUID_MIDI_ROUTER_RULE_NOTE);
/* Add rule to map all notes >= MIDI note #60 on any channel to channel 5 */
rule = new_fluid_midi_router_rule ();
fluid_midi_router_rule_set_chan (rule, 0, 15, 0.0, 5); /* Map all to channel 5 */
fluid_midi_router_rule_set_param1 (rule, 60, 127, 1.0, 0); /* Match notes >= 60 */
fluid_midi_router_add_rule (router, rule, FLUID_MIDI_ROUTER_RULE_NOTE);
/* Add rule to reverse direction of pitch bender on channel 7 */
rule = new_fluid_midi_router_rule ();
fluid_midi_router_rule_set_chan (rule, 7, 7, 1.0, 0); /* Match channel 7 only */
fluid_midi_router_rule_set_param1 (rule, 0, 16383, -1.0, 16383); /* Reverse pitch bender */
fluid_midi_router_add_rule (router, rule, FLUID_MIDI_ROUTER_RULE_PITCH_BEND);
/* ... Create audio driver, process events, etc ... */
/* cleanup */
delete_fluid_midi_router(router);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return 0;
}
\endcode
*/

View file

@ -0,0 +1,15 @@
/*!
\page Multi-channel Multi-channel audio rendering
FluidSynth is capable of rendering all audio and all effects from all MIDI
channels to separate stereo buffers. Refer to the documentation of
fluid_synth_process() and review the different use-cases in the example file
for information on how to do that: \ref fluidsynth_process.c
The following chart illustrates how the voices (produced by MIDI NoteOns) are
dispatched or mapped to their dry/effects audio buffers.
\image html fluid_mixer.svg "FluidSynth Mixer Chart"
*/

View file

@ -0,0 +1,46 @@
/*!
\page RealtimeMIDI Creating a real-time MIDI driver
FluidSynth can process real-time MIDI events received from hardware MIDI
ports or other applications. To do so, the client must create a MIDI input
driver. It is a very similar process to the creation of the audio driver: you
initialize some properties in a settings instance and call the
new_fluid_midi_driver() function providing a callback function that will be
invoked when a MIDI event is received. The following MIDI drivers are
currently supported:
- jack: JACK Audio Connection Kit MIDI driver (Linux, Mac OS X)
- oss: Open Sound System raw MIDI (Linux, Unix)
- alsa_raw: ALSA raw MIDI interface (Linux)
- alsa_seq: ALSA sequencer MIDI interface (Linux)
- winmidi: Microsoft Windows MM System (Windows)
- midishare: MIDI Share (Linux, Mac OS X)
- coremidi: Apple CoreMIDI (Mac OS X)
\code
#include <fluidsynth.h>
int handle_midi_event(void* data, fluid_midi_event_t* event)
{
printf("event type: %d\n", fluid_midi_event_get_type(event));
}
int main(int argc, char** argv)
{
fluid_settings_t* settings;
fluid_midi_driver_t* mdriver;
settings = new_fluid_settings();
mdriver = new_fluid_midi_driver(settings, handle_midi_event, NULL);
/* ... */
delete_fluid_midi_driver(mdriver);
return 0;
}
\endcode
There are a number of general MIDI driver settings. The \setting{midi_driver} setting
defines the MIDI subsystem that will be used. There are additional settings
for the MIDI subsystems used. For a full list of available
<strong>midi driver settings</strong>, please refer to the \setting{midi} documentation.
*/

View file

@ -0,0 +1,53 @@
/*!
\page SendingMIDI Sending MIDI events
Once the synthesizer is up and running and a SoundFont is loaded, most people
will want to do something useful with it. Make noise, for example. MIDI
messages can be sent using the fluid_synth_noteon(), fluid_synth_noteoff(),
fluid_synth_cc(), fluid_synth_pitch_bend(), fluid_synth_pitch_wheel_sens(),
and fluid_synth_program_change() functions. For convenience, there's also a
fluid_synth_bank_select() function (the bank select message is normally sent
using a control change message).
The following example show a generic graphical button that plays a note when
clicked:
\code
class SoundButton : public SomeButton
{
public:
SoundButton() : SomeButton() {
if (!_synth) {
initSynth();
}
}
static void initSynth() {
_settings = new_fluid_settings();
_synth = new_fluid_synth(_settings);
_adriver = new_fluid_audio_driver(_settings, _synth);
}
/* ... */
virtual int handleMouseDown(int x, int y) {
/* Play a note on key 60 with velocity 100 on MIDI channel 0 */
fluid_synth_noteon(_synth, 0, 60, 100);
}
virtual int handleMouseUp(int x, int y) {
/* Release the note on key 60 */
fluid_synth_noteoff(_synth, 0, 60);
}
protected:
static fluid_settings_t* _settings;
static fluid_synth_t* _synth;
static fluid_audio_driver_t* _adriver;
};
\endcode
*/

142
doc/usage/sequencer.txt Normal file
View file

@ -0,0 +1,142 @@
/*!
\page Sequencer Using the MIDI sequencer
FluidSynth's 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.
The client program should first initialize the sequencer instance using the
function new_fluid_sequencer2(). There is a complementary function
delete_fluid_sequencer() to delete it. After creating the sequencer instance,
the destinations can be registered using
fluid_sequencer_register_fluidsynth() for the synthesizer destination, and
optionally using fluid_sequencer_register_client() for the client destination
providing a suitable callback function. It can be unregistered using
fluid_sequencer_unregister_client(). After the initialization, events can be
sent with fluid_sequencer_send_now() and scheduled to the future with
fluid_sequencer_send_at(). The registration functions return identifiers,
that can be used as destinations of an event using fluid_event_set_dest().
The function fluid_sequencer_get_tick() returns the current playing position.
A program may choose a new timescale in milliseconds using
fluid_sequencer_set_time_scale().
The following example uses the fluidsynth sequencer to implement a sort of
music box. FluidSynth internal clock is used to schedule repetitive sequences
of notes. The next sequence is scheduled on advance before the end of the
current one, using a timer event that triggers a callback function. The
scheduling times are always absolute values, to avoid slippage.
\code
#include "fluidsynth.h"
fluid_synth_t* synth;
fluid_audio_driver_t* adriver;
fluid_sequencer_t* sequencer;
short synthSeqID, mySeqID;
unsigned int now;
unsigned int seqduration;
// prototype
void seq_callback(unsigned int time, fluid_event_t* event, fluid_sequencer_t* seq, void* data);
void createsynth()
{
fluid_settings_t* settings;
settings = new_fluid_settings();
fluid_settings_setint(settings, "synth.reverb.active", 0);
fluid_settings_setint(settings, "synth.chorus.active", 0);
synth = new_fluid_synth(settings);
adriver = new_fluid_audio_driver(settings, synth);
sequencer = new_fluid_sequencer2(0);
// register synth as first destination
synthSeqID = fluid_sequencer_register_fluidsynth(sequencer, synth);
// register myself as second destination
mySeqID = fluid_sequencer_register_client(sequencer, "me", seq_callback, NULL);
// the sequence duration, in ms
seqduration = 1000;
}
void deletesynth()
{
delete_fluid_sequencer(sequencer);
delete_fluid_audio_driver(adriver);
delete_fluid_synth(synth);
}
void loadsoundfont()
{
int fluid_res;
// put your own path here
fluid_res = fluid_synth_sfload(synth, "Inside:VintageDreamsWaves-v2.sf2", 1);
}
void sendnoteon(int chan, short key, unsigned int date)
{
int fluid_res;
fluid_event_t *evt = new_fluid_event();
fluid_event_set_source(evt, -1);
fluid_event_set_dest(evt, synthSeqID);
fluid_event_noteon(evt, chan, key, 127);
fluid_res = fluid_sequencer_send_at(sequencer, evt, date, 1);
delete_fluid_event(evt);
}
void schedule_next_callback()
{
int fluid_res;
// I want to be called back before the end of the next sequence
unsigned int callbackdate = now + seqduration/2;
fluid_event_t *evt = new_fluid_event();
fluid_event_set_source(evt, -1);
fluid_event_set_dest(evt, mySeqID);
fluid_event_timer(evt, NULL);
fluid_res = fluid_sequencer_send_at(sequencer, evt, callbackdate, 1);
delete_fluid_event(evt);
}
void schedule_next_sequence() {
// Called more or less before each sequence start
// the next sequence start date
now = now + seqduration;
// the sequence to play
// the beat : 2 beats per sequence
sendnoteon(0, 60, now + seqduration/2);
sendnoteon(0, 60, now + seqduration);
// melody
sendnoteon(1, 45, now + seqduration/10);
sendnoteon(1, 50, now + 4*seqduration/10);
sendnoteon(1, 55, now + 8*seqduration/10);
// so that we are called back early enough to schedule the next sequence
schedule_next_callback();
}
/* sequencer callback */
void seq_callback(unsigned int time, fluid_event_t* event, fluid_sequencer_t* seq, void* data) {
schedule_next_sequence();
}
int main(void) {
createsynth();
loadsoundfont();
// initialize our absolute date
now = fluid_sequencer_get_tick(sequencer);
schedule_next_sequence();
sleep(100000);
deletesynth();
return 0;
}
\endcode
*/

12
doc/usage/shell.txt Normal file
View file

@ -0,0 +1,12 @@
/*!
\page Shell Shell interface
The shell interface allows you to send simple textual commands to the
synthesizer, to parse a command file, or to read commands from the stdin or
other input streams. To find the list of currently supported commands, type
@c help in the fluidsynth command line shell. For a full list of available
<strong>command line settings</strong>, please refer to the \ref
settings_shell documentation.
*/

View file

@ -0,0 +1,30 @@
/*!
\page synth-context Understanding the "synthesis context"
When reading through the functions exposed via our API, you will often read the
note: "May or may not be called from synthesis context."
The reason for this is that some functions are intentionally not thread-safe.
Or they require to be called from this context to behave correctly.
FluidSynth's rendering engine is implemented by using the "Dispatcher Thread
Pattern". This means that a certain thread @c A which calls one of FluidSynth's
rendering functions, namely
- fluid_synth_process()
- fluid_synth_nwrite_float()
- fluid_synth_write_float()
- fluid_synth_write_s16()
automatically becomes the "synthesis thread". The terms "synthesis context" and
"synthesis thread" are equivalent. A few locations in our API provide hooks
that allow you to interfere this "synthesis context". At those locations you
can register your own custom functions that will always be called by thread
@c A. For this use-case, the following functions are of interest:
- new_fluid_audio_driver2()
- fluid_player_set_playback_callback()
- fluid_sequencer_register_client()
*/

View file

@ -26,29 +26,39 @@ extern "C" {
#endif
/**
* @file audio.h
* @brief Functions for audio driver output.
* @defgroup AudioFunctions Functions for audio output
* @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
* 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. 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).
* For further details please refer to fluid_synth_process().
* @note Whereas fluid_synth_process() allows aliasing buffers, there is the guarentee 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 accidentially to the same buffer multiple times.
* 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.
@ -56,11 +66,22 @@ extern "C" {
* @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).
* For further details please refer to fluid_synth_process().
*
* @note Whereas fluid_synth_process() allows aliasing buffers, there is the guarentee 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 accidentially to the same buffer multiple times.
*
*/
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);
@ -69,13 +90,36 @@ FLUIDSYNTH_API fluid_audio_driver_t *new_fluid_audio_driver2(fluid_settings_t *s
void *data);
FLUIDSYNTH_API void delete_fluid_audio_driver(fluid_audio_driver_t *driver);
FLUIDSYNTH_API fluid_file_renderer_t *new_fluid_file_renderer(fluid_synth_t *synth);
FLUIDSYNTH_API int fluid_file_renderer_process_block(fluid_file_renderer_t *dev);
FLUIDSYNTH_API void delete_fluid_file_renderer(fluid_file_renderer_t *dev);
FLUIDSYNTH_API int fluid_file_set_encoding_quality(fluid_file_renderer_t *dev, double q);
/** @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
}

View file

@ -26,10 +26,12 @@ extern "C" {
#endif
/**
* @file event.h
* @brief Sequencer event functions and defines.
* @defgroup sequencer_events Sequencer Events
* @ingroup sequencer
*
* Functions and constants for creating/processing sequencer events.
* Create, modify, query and destroy sequencer events.
*
* @{
*/
/**
@ -59,14 +61,16 @@ enum fluid_seq_event_type
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 */
#ifndef __DOXYGEN__
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! */
#endif
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);
@ -126,6 +130,7 @@ 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 unsigned int fluid_event_get_sfont_id(fluid_event_t *evt);
/* @} */
#ifdef __cplusplus
}

View file

@ -26,8 +26,12 @@ extern "C" {
#endif
/**
* @file gen.h
* @brief Functions and defines for SoundFont generator effects.
* @defgroup generators SoundFont Generators
* @ingroup soundfonts
*
* Functions and defines for SoundFont generator effects.
*
* @{
*/
/**
@ -96,7 +100,7 @@ enum fluid_gen_type
GEN_OVERRIDEROOTKEY, /**< Sample root note override */
/**
* @brief Initial Pitch
* Initial Pitch
*
* @note This is not "standard" SoundFont generator, because it is not
* mentioned in the list of generators in the SF2 specifications.
@ -117,11 +121,11 @@ enum fluid_gen_type
GEN_CUSTOM_FILTERFC, /**< Custom filter cutoff frequency */
GEN_CUSTOM_FILTERQ, /**< Custom filter Q */
#ifndef __DOXYGEN__
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! */
#endif
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
}

View file

@ -26,16 +26,19 @@ extern "C" {
#endif
/**
* @file ladspa.h
* @brief Functions for manipulating the ladspa effects unit
* @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.
* 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);
@ -56,6 +59,7 @@ FLUIDSYNTH_API int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const
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
}

View file

@ -28,25 +28,31 @@ extern "C" {
/**
* @file log.h
* @brief Logging interface
* @defgroup logging Logging
*
* The default logging function of the fluidsynth prints its messages
* to the stderr. The synthesizer uses five level of messages: #FLUID_PANIC,
* 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:
* 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);
* 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.
*
* @{
*/
/**
@ -59,13 +65,13 @@ enum fluid_log_level
FLUID_WARN, /**< Warning */
FLUID_INFO, /**< Verbose informational messages */
FLUID_DBG, /**< Debugging messages */
#ifndef __DOXYGEN__
LAST_LOG_LEVEL /**< @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
#endif
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().
@ -82,7 +88,7 @@ FLUIDSYNTH_API int fluid_log(int level, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)))
#endif
;
/* @} */
#ifdef __cplusplus
}

View file

@ -26,12 +26,55 @@ extern "C" {
#endif
/**
* @file midi.h
* @brief Functions for MIDI events, drivers and MIDI file playback.
* @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);
/* @} */
/**
* @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(fluid_midi_event_t *evt);
@ -59,9 +102,20 @@ 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 tranformation and filtering of MIDI events.
*
* @{
*/
/**
* MIDI router rule type.
*
* @since 1.1.0
*/
typedef enum
@ -72,35 +126,30 @@ typedef enum
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 */
#ifndef __DOXYGEN__
FLUID_MIDI_ROUTER_RULE_COUNT /**< @internal Total count of rule types @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time!*/
#endif
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;
/**
* Generic callback function for MIDI events.
* @param data User defined data pointer
* @param event The MIDI event
* @return Should return #FLUID_OK on success, #FLUID_FAILED otherwise
*
* Will be used between
* - MIDI driver and MIDI router
* - MIDI router and synth
* to communicate events.
* In the not-so-far future...
*/
typedef int (*handle_midi_event_func_t)(void *data, fluid_midi_event_t *event);
/** @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,
@ -110,15 +159,47 @@ FLUIDSYNTH_API void fluid_midi_router_rule_set_param2(fluid_midi_router_rule_t *
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 Player
* @ingroup midi_input
*
* Parse standard MIDI files and emit MIDI events.
*
* @{
*/
/**
* MIDI player status enum.
@ -131,8 +212,11 @@ enum fluid_player_status
FLUID_PLAYER_DONE /**< Player is finished playing */
};
/** @startlifecycle{MIDI 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);
@ -149,8 +233,7 @@ 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
}

View file

@ -28,13 +28,15 @@ extern "C" {
/**
* @file misc.h
* @brief Miscellaneous utility functions and defines
* @defgroup misc Miscellaneous
*
* Miscellaneous utility functions and defines
*
* @{
*/
/**
* Value that indicates success, used by most libfluidsynth functions.
* @since 1.1.0
*
* @note This was not publicly defined prior to libfluidsynth 1.1.0. When
* writing code which should also be compatible with older versions, something
@ -48,14 +50,17 @@ extern "C" {
* #define FLUID_FAILED (-1)
* #endif
* @endcode
*
* @since 1.1.0
*/
#define FLUID_OK (0)
/**
* Value that indicates failure, used by most libfluidsynth functions.
* @since 1.1.0
*
* @note See #FLUID_OK for more details.
*
* @since 1.1.0
*/
#define FLUID_FAILED (-1)
@ -63,7 +68,7 @@ extern "C" {
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
}

View file

@ -26,11 +26,14 @@ extern "C" {
#endif
/**
* @file mod.h
* @brief SoundFont modulator functions and constants.
* @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.
@ -69,8 +72,11 @@ enum fluid_mod_src
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);
@ -90,6 +96,7 @@ 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
}

View file

@ -26,12 +26,21 @@ extern "C" {
#endif
/**
* @file seq.h
* @brief MIDI event sequencer.
* @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
@ -41,9 +50,12 @@ 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,
@ -63,6 +75,7 @@ void fluid_sequencer_remove_events(fluid_sequencer_t *seq, fluid_seq_id_t source
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
}

View file

@ -28,15 +28,15 @@ extern "C" {
#endif
/**
* @file seqbind.h
* @brief Functions for binding sequencer objects to other subsystems.
* @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
}

View file

@ -26,9 +26,9 @@ extern "C" {
#endif
/**
* @file settings.h
* @brief Synthesizer settings
* @defgroup SettingsFunctions Functions for settings management
* @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.
@ -49,6 +49,8 @@ extern "C" {
* }
* @endcode
* @sa @ref CreatingSettings
*
* @{
*/
/**
@ -97,9 +99,10 @@ enum fluid_types_enum
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);
@ -153,6 +156,7 @@ int fluid_settings_getint_range(fluid_settings_t *settings, const char *name,
/**
* 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)
@ -171,6 +175,7 @@ FLUIDSYNTH_API char *fluid_settings_option_concat(fluid_settings_t *settings,
/**
* 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)
@ -180,6 +185,7 @@ 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
}

View file

@ -25,10 +25,21 @@
extern "C" {
#endif
/**
* @defgroup soundfonts SountFonts
*
* 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.
*/
/**
* @file sfont.h
* @brief SoundFont plugins
* @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
@ -59,6 +70,8 @@ extern "C" {
* 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.
*
* @{
*/
/**
@ -75,6 +88,7 @@ enum
/**
* 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.
*/
@ -92,6 +106,7 @@ enum fluid_sample_type
/**
* 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.
@ -100,24 +115,31 @@ typedef fluid_sfont_t *(*fluid_sfloader_load_t)(fluid_sfloader_t *loader, const
/**
* The free method should free the memory allocated for a fluid_sfloader_t instance in
* addition to any private data. Any custom user provided cleanup function must ultimately call
* 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.
* @param loader SoundFont loader
*
*/
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.
* \c filename matches the string provided during the fluid_synth_sfload() call.
*
* @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);
@ -132,7 +154,6 @@ typedef int (* fluid_sfloader_callback_read_t)(void *buf, fluid_long_long_t coun
* 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);
@ -162,6 +183,7 @@ 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.
*/
@ -169,6 +191,7 @@ 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)
@ -179,6 +202,7 @@ typedef fluid_preset_t *(*fluid_sfont_get_preset_t)(fluid_sfont_t *sfont, int ba
/**
* Start virtual SoundFont preset iteration method.
*
* @param sfont Virtual SoundFont
*
* Starts/re-starts virtual preset iteration in a SoundFont.
@ -187,6 +211,7 @@ 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
*
@ -196,17 +221,21 @@ typedef void (*fluid_sfont_iteration_start_t)(fluid_sfont_t *sfont);
typedef fluid_preset_t *(*fluid_sfont_iteration_next_t)(fluid_sfont_t *sfont);
/**
* Method to free a virtual SoundFont bank. 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.
* 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,
@ -214,6 +243,7 @@ FLUIDSYNTH_API fluid_sfont_t *new_fluid_sfont(fluid_sfont_get_name_t get_name,
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);
@ -226,6 +256,7 @@ 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
@ -235,6 +266,7 @@ 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
*/
@ -242,6 +274,7 @@ 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
*/
@ -249,6 +282,7 @@ 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
@ -272,14 +306,18 @@ typedef int (*fluid_preset_get_num_t)(fluid_preset_t *preset);
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. 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.
* 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,
@ -287,6 +325,7 @@ FLUIDSYNTH_API fluid_preset_t *new_fluid_preset(fluid_sfont_t *parent_sfont,
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);
@ -296,8 +335,11 @@ 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);
@ -311,6 +353,8 @@ FLUIDSYNTH_API int fluid_sample_set_sound_data(fluid_sample_t *sample,
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

View file

@ -28,59 +28,101 @@ extern "C" {
/**
* @file shell.h
* @brief Command shell interface
* @defgroup command_interface Command Interface
*
* The shell interface allows you to send simple textual commands to
* 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.
* 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);
/* @} */
/* The command handler */
/**
* @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
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);
/* Command function */
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);
FLUIDSYNTH_API
void fluid_usershell(fluid_settings_t *settings, fluid_cmd_handler_t *handler);
/* @} */
/* Shell */
/**
* @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.
*
* @{
*/
/* TCP/IP server */
/** @startlifecycle{Command Server} */
FLUIDSYNTH_API
fluid_server_t *new_fluid_server(fluid_settings_t *settings,
fluid_synth_t *synth, fluid_midi_router_t *router);
@ -88,7 +130,9 @@ fluid_server_t *new_fluid_server(fluid_settings_t *settings,
FLUIDSYNTH_API void delete_fluid_server(fluid_server_t *server);
FLUIDSYNTH_API int fluid_server_join(fluid_server_t *server);
/** @endlifecycle */
/* @} */
#ifdef __cplusplus
}

View file

@ -28,8 +28,9 @@ extern "C" {
/**
* @file synth.h
* @brief Embeddable SoundFont synthesizer
* @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
@ -43,15 +44,29 @@ extern "C" {
*
* 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);
FLUIDSYNTH_API fluid_settings_t *fluid_synth_get_settings(fluid_synth_t *synth);
/** @endlifecycle */
/* MIDI channel messages */
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);
@ -84,37 +99,42 @@ 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 */
/* Dynamic sample loading */
FLUIDSYNTH_API
int fluid_synth_pin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num);
FLUIDSYNTH_API
int fluid_synth_unpin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num);
/**
* The midi channel type used by fluid_synth_set_channel_type()
* @defgroup voice_control Synthesis Voice Control
* @ingroup synth
*
* Low-level access to synthesis voices.
*
* @{
*/
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);
/* Low level access */
FLUIDSYNTH_API fluid_preset_t *fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan);
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 */
/* SoundFont management */
/**
* @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);
@ -128,11 +148,17 @@ 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 */
/* Reverb */
/**
* @defgroup reverb_effect Effect - Reverb
* @ingroup synth
*
* Functions for configuring the built-in reverb effect
*
* @{
*/
FLUIDSYNTH_API int fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize,
double damping, double width, double level);
FLUIDSYNTH_API int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize);
@ -145,9 +171,17 @@ FLUIDSYNTH_API double fluid_synth_get_reverb_roomsize(fluid_synth_t *synth);
FLUIDSYNTH_API double fluid_synth_get_reverb_damp(fluid_synth_t *synth);
FLUIDSYNTH_API double fluid_synth_get_reverb_level(fluid_synth_t *synth);
FLUIDSYNTH_API double fluid_synth_get_reverb_width(fluid_synth_t *synth);
/* @} Reverb */
/* Chorus */
/**
* @defgroup chorus_effect Effect - Chorus
* @ingroup synth
*
* Functions for configuring the built-in chorus effect
*
* @{
*/
/**
* Chorus modulation waveform type.
@ -172,19 +206,24 @@ FLUIDSYNTH_API double fluid_synth_get_chorus_level(fluid_synth_t *synth);
FLUIDSYNTH_API double fluid_synth_get_chorus_speed(fluid_synth_t *synth);
FLUIDSYNTH_API double fluid_synth_get_chorus_depth(fluid_synth_t *synth);
FLUIDSYNTH_API int fluid_synth_get_chorus_type(fluid_synth_t *synth); /* see fluid_chorus_mod */
/* @} Chrous */
/* Audio and MIDI channels */
/**
* @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);
/* Synthesis parameters */
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);
@ -210,15 +249,28 @@ enum fluid_interp
FLUID_INTERP_HIGHEST = FLUID_INTERP_7THORDER, /**< Highest interpolation method */
};
/* Generator interface */
/**
* 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_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);
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 */
/* Tuning */
/**
* @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);
@ -238,36 +290,23 @@ 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 */
/* Misc */
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);
/* Default modulators */
/**
* 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);
/*
* Synthesizer plugin
* @defgroup audio_rendering Audio Rendering
* @ingroup synth
*
* To create a synthesizer plugin, create the synthesizer as
* explained above. Once the synthesizer is created you can call
* any of the functions below to get the audio.
* 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.
*
* @{
*/
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);
@ -280,18 +319,17 @@ FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_nwrite_float(fluid_synth_t *synt
FLUIDSYNTH_API int fluid_synth_process(fluid_synth_t *synth, int len,
int nfx, float *fx[],
int nout, float *out[]);
/* @} Audio Rendering */
/* Synthesizer's interface to handle SoundFont loaders */
FLUIDSYNTH_API void fluid_synth_add_sfloader(fluid_synth_t *synth, fluid_sfloader_t *loader);
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);
FLUIDSYNTH_API int fluid_synth_handle_midi_event(void *data, fluid_midi_event_t *event);
/**
* @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
@ -315,17 +353,43 @@ enum fluid_iir_filter_flags
};
FLUIDSYNTH_API int fluid_synth_set_custom_filter(fluid_synth_t *, int type, int flags);
/* @} IIR Filter */
/* LADSPA */
FLUIDSYNTH_API fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth);
/* API: Poly mono mode */
/** Interface to poly/mono mode variables
/**
* @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
@ -334,15 +398,9 @@ enum fluid_channel_mode_flags
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 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 */
};
/** Indicates the mode a basic channel is set to */
/**
* 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 */
@ -361,8 +419,13 @@ FLUIDSYNTH_API int fluid_synth_get_basic_channel(fluid_synth_t *synth, int chan
int *basic_val_out);
FLUIDSYNTH_API int fluid_synth_set_basic_channel(fluid_synth_t *synth, int chan, int mode, int val);
/** Interface to mono legato mode
*
/** @} 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
@ -374,9 +437,13 @@ enum fluid_channel_legato_mode
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 */
/** Interface to portamento mode
*
/** @name Portamento Mode
* @{
*/
/**
* Indicates the portamento mode a channel is set to
*/
enum fluid_channel_portamento_mode
@ -384,21 +451,62 @@ 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 (#fluid_channel_portamento_mode) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
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 */
};
/* Interface to breath mode */
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

View file

@ -29,8 +29,10 @@ extern "C" {
/**
* @file types.h
* @defgroup Types Types
* @brief Type declarations
*
* @{
*/
typedef struct _fluid_hashtable_t fluid_settings_t; /**< Configuration settings instance */
@ -74,6 +76,8 @@ typedef __int64 fluid_long_long_t; // even on 32bit windows
typedef long long fluid_long_long_t;
#endif
/* @} */
#ifdef __cplusplus
}
#endif

View file

@ -27,10 +27,10 @@ extern "C" {
#endif
/**
* @file version.h
* @brief Library version functions and defines
* @addtogroup misc
*
* @{
*/
#define FLUIDSYNTH_VERSION @FLUIDSYNTH_VERSION@ /**< String constant of libfluidsynth version. */
#define FLUIDSYNTH_VERSION_MAJOR @FLUIDSYNTH_VERSION_MAJOR@ /**< libfluidsynth major version integer constant. */
#define FLUIDSYNTH_VERSION_MINOR @FLUIDSYNTH_VERSION_MINOR@ /**< libfluidsynth minor version integer constant. */
@ -38,7 +38,7 @@ extern "C" {
FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro);
FLUIDSYNTH_API char* fluid_version_str(void);
/* @} */
#ifdef __cplusplus
}

View file

@ -26,16 +26,21 @@ extern "C" {
#endif
/**
* @file voice.h
* @brief Synthesis voice manipulation functions.
* @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 fluid_defsfont.c.
* 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.
*/
@ -63,7 +68,7 @@ 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
}

View file

@ -386,12 +386,14 @@ static const fluid_cmd_t fluid_commands[] =
/**
* Process a string command.
* NOTE: FluidSynth 1.0.8 and above no longer modifies the 'cmd' string.
*
* @param handler FluidSynth command handler
* @param cmd Command string (NOTE: Gets modified by FluidSynth prior to 1.0.8)
* @param out Output stream to display command response to
* @return Integer value corresponding to: -1 on command error, 0 on success,
* 1 if 'cmd' is a comment or is empty and -2 if quit was issued
*
* @note FluidSynth 1.0.8 and above no longer modifies the 'cmd' string.
*/
int
fluid_command(fluid_cmd_handler_t *handler, const char *cmd, fluid_ostream_t out)
@ -418,6 +420,7 @@ fluid_command(fluid_cmd_handler_t *handler, const char *cmd, fluid_ostream_t out
/**
* Create a new FluidSynth command shell.
*
* @param settings Setting parameters to use with the shell
* @param handler Command handler
* @param in Input stream
@ -550,8 +553,12 @@ fluid_shell_run(void *data)
/**
* A convenience function to create a shell interfacing to standard input/output
* console streams.
*
* @param settings Settings instance for the shell
* @param handler Command handler callback
*
* The shell is run in the current thread, this function will only
* return after the \c quit command has been issued.
*/
void
fluid_usershell(fluid_settings_t *settings, fluid_cmd_handler_t *handler)
@ -563,6 +570,7 @@ fluid_usershell(fluid_settings_t *settings, fluid_cmd_handler_t *handler)
/**
* Execute shell commands in a file.
*
* @param handler Command handler callback
* @param filename File name
* @return 0 on success, a negative value on error
@ -600,11 +608,12 @@ fluid_source(fluid_cmd_handler_t *handler, const char *filename)
/**
* Get the user specific FluidSynth command file name.
*
* On Windows this is currently @c "%USERPROFILE%\fluidsynth.cfg".
* For anything else (except MACOS9) @c "$HOME/.fluidsynth".
* @param buf Caller supplied string buffer to store file name to.
* @param len Length of \a buf
* @return Returns \a buf pointer or NULL if no user command file for this system type.
*
* On Windows this is currently @c "%USERPROFILE%\fluidsynth.cfg".
* For anything else (except MACOS9) @c "$HOME/.fluidsynth".
*/
char *
fluid_get_userconf(char *buf, int len)
@ -635,11 +644,12 @@ fluid_get_userconf(char *buf, int len)
/**
* Get the system FluidSynth command file name.
*
* Windows and MACOS9 do not have a system-wide config file currently. For anything else it
* returns @c "/etc/fluidsynth.conf".
* @param buf Caller supplied string buffer to store file name to.
* @param len Length of \a buf
* @return Returns \a buf pointer or NULL if no system command file for this system type.
*
* Windows and MACOS9 do not have a system-wide config file currently. For anything else it
* returns @c "/etc/fluidsynth.conf".
*/
char *
fluid_get_sysconf(char *buf, int len)
@ -4151,6 +4161,7 @@ fluid_cmd_handler_destroy_hash_value(void *value)
/**
* Create a new command handler.
*
* @param synth If not NULL, all the default synthesizer commands will be added to the new handler.
* @param router If not NULL, all the default midi_router commands will be added to the new handler.
* @return New command handler, or NULL if alloc failed
@ -4200,6 +4211,7 @@ fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_rout
/**
* Delete a command handler.
*
* @param handler Command handler to delete
*/
void
@ -4213,6 +4225,7 @@ delete_fluid_cmd_handler(fluid_cmd_handler_t *handler)
/**
* Register a new command to the handler.
*
* @param handler Command handler instance
* @param cmd Command info (gets copied)
* @return #FLUID_OK if command was inserted, #FLUID_FAILED otherwise
@ -4227,6 +4240,7 @@ fluid_cmd_handler_register(fluid_cmd_handler_t *handler, const fluid_cmd_t *cmd)
/**
* Unregister a command from a command handler.
*
* @param handler Command handler instance
* @param cmd Name of the command
* @return TRUE if command was found and unregistered, FALSE otherwise
@ -4415,6 +4429,7 @@ void delete_fluid_client(fluid_client_t *client)
/**
* Create a new TCP/IP command shell server.
*
* @param settings Settings instance to use for the shell
* @param synth If not NULL, the synth instance for the command handler to be used by the client
* @param router If not NULL, the midi_router instance for the command handler to be used by the client
@ -4464,6 +4479,7 @@ new_fluid_server(fluid_settings_t *settings,
/**
* Delete a TCP/IP shell server.
*
* @param server Shell server instance
*/
void
@ -4480,6 +4496,7 @@ delete_fluid_server(fluid_server_t *server)
/**
* Join a shell server thread (wait until it quits).
*
* @param server Shell server instance
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/

View file

@ -171,22 +171,24 @@ fluid_file_renderer_settings(fluid_settings_t *settings)
/**
* 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
* @since 1.1.0
*
* NOTE: Available file types and formats depends on if libfluidsynth was
* @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:
* - audio.file.name: Output filename
* - audio.file.type: File type, "auto" tries to determine type from filename
* - \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".
* - audio.file.format: Audio format
* - audio.file.endian: Endian byte order, "auto" for file type's default byte order
* - audio.period-size: Size of audio blocks to process
* - synth.sample-rate: Sample rate to use
* - \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)

View file

@ -227,15 +227,16 @@ error_recovery:
}
/**
* Destroys and frees a LADSPA effects unit previously created
* with new_fluid_ladspa_fx.
* Destroy and free a LADSPA effects unit previously created
* with new_fluid_ladspa_fx().
*
* @param fx LADSPA effects instance
*
* @note This function does not check the engine state for
* possible users, so make sure that you only call this
* if you are sure nobody is using the engine anymore (especially
* that nobody calls fluid_ladspa_run)
*
* @param fx LADSPA effects instance
*/
void delete_fluid_ladspa_fx(fluid_ladspa_fx_t *fx)
{
@ -268,15 +269,16 @@ void delete_fluid_ladspa_fx(fluid_ladspa_fx_t *fx)
/**
* Add host buffers to the LADSPA engine.
*
* @note The size of the buffers pointed to by the buffers array must be
* at least as large as the buffer size given to new_fluid_ladspa_fx.
*
* @param fx LADSPA fx instance
* @param prefix common name prefix for the created nodes
* @param num_buffers number of of buffers buffer array
* @param buffers array of sample buffers
* @param buf_stride number of samples contained in one buffer
* @return FLUID_OK on success, otherwise FLUID_FAILED
*
* @note The size of the buffers pointed to by the buffers array must be
* at least as large as the buffer size given to new_fluid_ladspa_fx.
*
*/
int fluid_ladspa_add_host_ports(fluid_ladspa_fx_t *fx, const char *prefix,
int num_buffers, fluid_real_t buffers[], int buf_stride)
@ -319,12 +321,13 @@ int fluid_ladspa_add_host_ports(fluid_ladspa_fx_t *fx, const char *prefix,
/**
* Set the sample rate of the LADSPA effects.
*
* Resets the LADSPA effects if the sample rate is different from the
* previous sample rate.
*
* @param fx LADSPA fx instance
* @param sample_rate new sample rate
* @return FLUID_OK on success, otherwise FLUID_FAILED
*
* Resets the LADSPA effects if the sample rate is different from the
* previous sample rate.
*
*/
int fluid_ladspa_set_sample_rate(fluid_ladspa_fx_t *fx, fluid_real_t sample_rate)
{
@ -357,13 +360,13 @@ int fluid_ladspa_set_sample_rate(fluid_ladspa_fx_t *fx, fluid_real_t sample_rate
/**
* Check if the LADSPA engine is currently used to render audio
*
* @param fx LADSPA fx instance
* @return TRUE if LADSPA effects engine is active, otherwise FALSE
*
* If an engine is active, the only allowed user actions are deactivation or
* setting values of control ports on effects. Anything else, especially
* adding or removing effects, buffers or ports, is only allowed in deactivated
* state.
*
* @param fx LADSPA fx instance
* @return TRUE if LADSPA effects engine is active, otherwise FALSE
*/
int fluid_ladspa_is_active(fluid_ladspa_fx_t *fx)
{
@ -424,10 +427,10 @@ int fluid_ladspa_activate(fluid_ladspa_fx_t *fx)
/**
* Deactivate a LADSPA fx instance and all configured effects.
*
* @note This function may sleep.
*
* @param fx LADSPA fx instance
* @return FLUID_OK if deactivation succeeded, otherwise FLUID_FAILED
*
* @note This function may sleep.
*/
int fluid_ladspa_deactivate(fluid_ladspa_fx_t *fx)
{
@ -468,11 +471,13 @@ int fluid_ladspa_deactivate(fluid_ladspa_fx_t *fx)
}
/**
* Reset the LADSPA effects engine: Deactivate LADSPA if currently active, remove all
* effects, remove all user nodes and unload all libraries.
* Reset the LADSPA effects engine.
*
* @param fx LADSPA fx instance
* @return FLUID_OK on success, otherwise FLUID_FAILED
*
* Deactivate LADSPA if currently active, remove all
* effects, remove all user nodes and unload all libraries.
*/
int fluid_ladspa_reset(fluid_ladspa_fx_t *fx)
{
@ -496,15 +501,15 @@ int fluid_ladspa_reset(fluid_ladspa_fx_t *fx)
/**
* Processes audio data via the LADSPA effects unit.
*
* @param fx LADSPA effects instance
* @param block_count number of blocks to render
* @param block_size number of samples in a block
*
* FluidSynth calls this function during main output mixing, just after
* the internal reverb and chorus effects have been processed.
*
* It copies audio data from the supplied buffers, runs all effects and copies the
* resulting audio back into the same buffers.
*
* @param fx LADSPA effects instance
* @param block_count number of blocks to render
* @param block_size number of samples in a block
*/
void fluid_ladspa_run(fluid_ladspa_fx_t *fx, int block_count, int block_size)
{
@ -862,7 +867,7 @@ int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const char *effect_na
}
/**
* Create an effect, i.e. an instance of a LADSPA plugin
* Create an instance of a LADSPA plugin as an effect
*
* @param fx LADSPA effects instance
* @param effect_name name of the effect
@ -922,14 +927,14 @@ int fluid_ladspa_add_effect(fluid_ladspa_fx_t *fx, const char *effect_name,
/**
* Connect an effect port to a host port or buffer
*
* @note There is no corresponding disconnect function. If the connections need to be changed,
* clear everything with fluid_ladspa_reset and start again from scratch.
*
* @param fx LADSPA effects instance
* @param effect_name name of the effect
* @param port_name the port name to connect to (case-insensitive prefix match)
* @param name the host port or buffer to connect to (case-insensitive)
* @return FLUID_OK on success, otherwise FLUID_FAILED
*
* @note There is no corresponding disconnect function. If the connections need to be changed,
* clear everything with fluid_ladspa_reset and start again from scratch.
*/
int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name,
const char *port_name, const char *name)
@ -1009,13 +1014,13 @@ int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name,
/**
* Do a sanity check for problems in the LADSPA setup
*
* If the check detects problems and the err pointer is not NULL, a description of the first found
* problem is written to that string (up to err_size - 1 characters).
*
* @param fx LADSPA fx instance
* @param err externally provided buffer for the error message. Set to NULL if you don't need an error message.
* @param err_size size of the err buffer
* @return FLUID_OK if setup is valid, otherwise FLUID_FAILED (err will contain the error message)
*
* If the check detects problems and the err pointer is not NULL, a description of the first found
* problem is written to that string (up to err_size - 1 characters).
*/
int fluid_ladspa_check(fluid_ladspa_fx_t *fx, char *err, int err_size)
{
@ -1139,13 +1144,13 @@ static fluid_ladspa_node_t *get_node(fluid_ladspa_fx_t *fx, const char *name)
/**
* Return a LADSPA effect port index by name, using a 'fuzzy match'.
*
* Returns the first effect port which matches the name. If no exact match is
* found, returns the port that starts with the specified name, but only if there is
* only one such match.
*
* @param effect pointer to fluid_ladspa_effect_t
* @param name the port name
* @return index of the port in the effect or -1 on error
*
* Returns the first effect port which matches the name. If no exact match is
* found, returns the port that starts with the specified name, but only if there is
* only one such match.
*/
static int get_effect_port_idx(const fluid_ladspa_effect_t *effect, const char *name)
{
@ -1178,11 +1183,11 @@ static int get_effect_port_idx(const fluid_ladspa_effect_t *effect, const char *
/**
* Return a LADSPA descriptor structure for a plugin in a LADSPA library.
*
* If name is optional if the library contains only one plugin.
*
* @param lib pointer to the dynamically loaded library
* @param name name (LADSPA Label) of the plugin
* @return pointer to LADSPA_Descriptor, NULL on error or if not found
*
* The name is optional if the library contains only one plugin.
*/
static const LADSPA_Descriptor *get_plugin_descriptor(fluid_module_t *lib, const char *name)
{
@ -1233,13 +1238,13 @@ static const LADSPA_Descriptor *get_plugin_descriptor(fluid_module_t *lib, const
* Instantiate a LADSPA plugin from a library and set up the associated
* control structures needed by the LADSPA fx engine.
*
* If the library contains only one plugin, then the name is optional.
* Plugins are identified by their "Label" in the plugin descriptor structure.
*
* @param fx LADSPA fx instance
* @param lib_name file path of the plugin library
* @param plugin_name (optional) string name of the plugin (the LADSPA Label)
* @return pointer to the new ladspa_plugin_t structure or NULL on error
*
* If the library contains only one plugin, then the name is optional.
* Plugins are identified by their "Label" in the plugin descriptor structure.
*/
static fluid_ladspa_effect_t *
new_fluid_ladspa_effect(fluid_ladspa_fx_t *fx, const char *lib_name, const char *plugin_name)

View file

@ -288,6 +288,7 @@ find_fluid_audio_driver(fluid_settings_t *settings)
/**
* Create a new audio driver.
*
* @param settings Configuration settings used to select and create the audio
* driver.
* @param synth Synthesizer instance for which the audio driver is created for.
@ -326,6 +327,7 @@ new_fluid_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
/**
* Create a new audio driver.
*
* @param settings Configuration settings used to select and create the audio
* driver.
* @param func Function called to fill audio buffers for audio playback
@ -378,6 +380,7 @@ new_fluid_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, voi
/**
* Deletes an audio driver instance.
*
* @param driver Audio driver instance to delete
*
* Shuts down an audio driver and deletes its instance.
@ -391,7 +394,11 @@ delete_fluid_audio_driver(fluid_audio_driver_t *driver)
/**
* @brief Registers audio drivers to use
* Registers audio drivers to use
*
* @param adrivers NULL-terminated array of audio drivers to register. Pass NULL to register all available drivers.
* @return #FLUID_OK if all the audio drivers requested by the user are supported by fluidsynth and have been
* successfully registered. Otherwise #FLUID_FAILED is returned and this function has no effect.
*
* When creating a settings instance with new_fluid_settings(), all audio drivers are initialized once.
* In the past this has caused segfaults and application crashes due to buggy soundcard drivers.
@ -407,11 +414,8 @@ delete_fluid_audio_driver(fluid_audio_driver_t *driver)
* are alive (e.g. as it would be the case right after fluidsynth's initial creation). Else the behaviour is undefined.
* Furtermore any attempt of using audio drivers that have not been registered is undefined behaviour!
*
* @param adrivers NULL-terminated array of audio drivers to register. Pass NULL to register all available drivers.
* @return #FLUID_OK if all the audio drivers requested by the user are supported by fluidsynth and have been
* successfully registered. Otherwise #FLUID_FAILED is returned and this function has no effect.
*
* @note This function is not thread safe and will never be!
*
* @since 1.1.9
*/
int fluid_audio_driver_register(const char **adrivers)

View file

@ -135,11 +135,14 @@ void fluid_midi_driver_settings(fluid_settings_t *settings)
/**
* Create a new MIDI driver instance.
* @param settings Settings used to configure new MIDI driver.
*
* @param settings Settings used to configure new MIDI driver. See \ref settings_midi for available options.
* @param handler MIDI handler callback (for example: fluid_midi_router_handle_midi_event()
* for MIDI router)
* @param event_handler_data Caller defined data to pass to 'handler'
* @return New MIDI driver instance or NULL on error
*
* Which MIDI driver is actually created depends on the \ref settings_midi_driver option.
*/
fluid_midi_driver_t *new_fluid_midi_driver(fluid_settings_t *settings, handle_midi_event_func_t handler, void *event_handler_data)
{

View file

@ -1798,16 +1798,18 @@ fluid_player_add_track(fluid_player_t *player, fluid_track_t *track)
}
/**
* Change the MIDI callback function. This is usually set to
* fluid_synth_handle_midi_event(), but can optionally be changed
* to a user-defined function instead, for intercepting all MIDI
* messages sent to the synth. You can also use a midi router as
* the callback function to modify the MIDI messages before sending
* them to the synth.
* Change the MIDI callback function.
*
* @param player MIDI player instance
* @param handler Pointer to callback function
* @param handler_data Parameter sent to the callback function
* @returns FLUID_OK
*
* This is usually set to fluid_synth_handle_midi_event(), but can optionally
* be changed to a user-defined function instead, for intercepting all MIDI
* messages sent to the synth. You can also use a midi router as the callback
* function to modify the MIDI messages before sending them to the synth.
*
* @since 1.1.4
*/
int
@ -2140,9 +2142,10 @@ fluid_player_play(fluid_player_t *player)
/**
* Pauses the MIDI playback.
*
* It will not rewind to the beginning of the file, use fluid_player_seek() for this purpose.
* @param player MIDI player instance
* @return Always returns #FLUID_OK
*
* It will not rewind to the beginning of the file, use fluid_player_seek() for this purpose.
*/
int
fluid_player_stop(fluid_player_t *player)
@ -2167,15 +2170,17 @@ fluid_player_get_status(fluid_player_t *player)
/**
* Seek in the currently playing file.
*
* The actual seek will be performed when the synth calls back the player (i.e. a few
* levels above the player's callback set with fluid_player_set_playback_callback()).
* If the player's status is #FLUID_PLAYER_PLAYING and a previous seek operation has
* not been completed yet, #FLUID_FAILED is returned.
* @param player MIDI player instance
* @param ticks the position to seek to in the current file
* @return #FLUID_FAILED if ticks is negative or after the latest tick of the file
* [or, since 2.1.3, if another seek operation is currently in progress],
* #FLUID_OK otherwise.
*
* The actual seek will be performed when the synth calls back the player (i.e. a few
* levels above the player's callback set with fluid_player_set_playback_callback()).
* If the player's status is #FLUID_PLAYER_PLAYING and a previous seek operation has
* not been completed yet, #FLUID_FAILED is returned.
*
* @since 2.0.0
*/
int fluid_player_seek(fluid_player_t *player, int ticks)
@ -2210,13 +2215,15 @@ int fluid_player_seek(fluid_player_t *player, int ticks)
/**
* Enable looping of a MIDI player
*
* @param player MIDI player instance
* @param loop Times left to loop the playlist. -1 means loop infinitely.
* @return Always returns #FLUID_OK
* @since 1.1.0
*
* For example, if you want to loop the playlist twice, set loop to 2
* and call this function before you start the player.
*
* @since 1.1.0
*/
int fluid_player_set_loop(fluid_player_t *player, int loop)
{

View file

@ -68,12 +68,15 @@ struct _fluid_midi_router_rule_t
/**
* Create a new midi router. The default rules will pass all events unmodified.
* Create a new midi router.
*
* @param settings Settings used to configure MIDI router
* @param handler MIDI event callback.
* @param event_handler_data Caller defined data pointer which gets passed to 'handler'
* @return New MIDI router instance or NULL on error
*
* The new router will start with default rules and therefore pass all events unmodified.
*
* The MIDI handler callback should process the possibly filtered/modified MIDI
* events from the MIDI router and forward them on to a synthesizer for example.
* The function fluid_synth_handle_midi_event() can be used for \a handle and
@ -151,10 +154,13 @@ delete_fluid_midi_router(fluid_midi_router_t *router)
}
/**
* Set a MIDI router to use default "unity" rules. Such a router will pass all
* events unmodified.
* Set a MIDI router to use default "unity" rules.
*
* @param router Router to set to default rules.
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*
* Such a router will pass all events unmodified.
*
* @since 1.1.0
*/
int
@ -244,10 +250,13 @@ fluid_midi_router_set_default_rules(fluid_midi_router_t *router)
}
/**
* Clear all rules in a MIDI router. Such a router will drop all events until
* rules are added.
* Clear all rules in a MIDI router.
*
* @param router Router to clear all rules from
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*
* An empty router will drop all events until rules are added.
*
* @since 1.1.0
*/
int
@ -357,11 +366,13 @@ fluid_midi_router_add_rule(fluid_midi_router_t *router, fluid_midi_router_rule_t
/**
* Create a new MIDI router rule.
*
* @return Newly allocated router rule or NULL if out of memory.
* @since 1.1.0
*
* The new rule is a "unity" rule which will accept any values and wont modify
* them.
*
* @since 1.1.0
*/
fluid_midi_router_rule_t *
new_fluid_midi_router_rule(void)
@ -396,11 +407,13 @@ new_fluid_midi_router_rule(void)
/**
* Free a MIDI router rule.
*
* @param rule Router rule to free
* @since 1.1.0
*
* Note that rules which have been added to a router are managed by the router,
* so this function should seldom be needed.
*
* @since 1.1.0
*/
void
delete_fluid_midi_router_rule(fluid_midi_router_rule_t *rule)
@ -411,12 +424,12 @@ delete_fluid_midi_router_rule(fluid_midi_router_rule_t *rule)
/**
* Set the channel portion of a rule.
*
* @param rule MIDI router rule
* @param min Minimum value for rule match
* @param max Maximum value for rule match
* @param mul Value which is multiplied by matching event's channel value (1.0 to not modify)
* @param add Value which is added to matching event's channel value (0 to not modify)
* @since 1.1.0
*
* The \a min and \a max parameters define a channel range window to match
* incoming events to. If \a min is less than or equal to \a max then an event
@ -426,6 +439,8 @@ delete_fluid_midi_router_rule(fluid_midi_router_rule_t *rule)
*
* The \a mul and \a add values are used to modify event channel values prior to
* sending the event, if the rule matches.
*
* @since 1.1.0
*/
void
fluid_midi_router_rule_set_chan(fluid_midi_router_rule_t *rule, int min, int max,
@ -440,12 +455,12 @@ fluid_midi_router_rule_set_chan(fluid_midi_router_rule_t *rule, int min, int max
/**
* Set the first parameter portion of a rule.
*
* @param rule MIDI router rule
* @param min Minimum value for rule match
* @param max Maximum value for rule match
* @param mul Value which is multiplied by matching event's 1st parameter value (1.0 to not modify)
* @param add Value which is added to matching event's 1st parameter value (0 to not modify)
* @since 1.1.0
*
* The 1st parameter of an event depends on the type of event. For note events
* its the MIDI note #, for CC events its the MIDI control number, for program
@ -464,6 +479,8 @@ fluid_midi_router_rule_set_chan(fluid_midi_router_rule_t *rule, int min, int max
*
* The \a mul and \a add values are used to modify event 1st parameter values prior to
* sending the event, if the rule matches.
*
* @since 1.1.0
*/
void
fluid_midi_router_rule_set_param1(fluid_midi_router_rule_t *rule, int min, int max,
@ -478,12 +495,12 @@ fluid_midi_router_rule_set_param1(fluid_midi_router_rule_t *rule, int min, int m
/**
* Set the second parameter portion of a rule.
*
* @param rule MIDI router rule
* @param min Minimum value for rule match
* @param max Maximum value for rule match
* @param mul Value which is multiplied by matching event's 2nd parameter value (1.0 to not modify)
* @param add Value which is added to matching event's 2nd parameter value (0 to not modify)
* @since 1.1.0
*
* The 2nd parameter of an event depends on the type of event. For note events
* its the MIDI velocity, for CC events its the control value and for key pressure
@ -499,6 +516,8 @@ fluid_midi_router_rule_set_param1(fluid_midi_router_rule_t *rule, int min, int m
*
* The \a mul and \a add values are used to modify event 2nd parameter values prior to
* sending the event, if the rule matches.
*
* @since 1.1.0
*/
void
fluid_midi_router_rule_set_param2(fluid_midi_router_rule_t *rule, int min, int max,

View file

@ -82,10 +82,13 @@ typedef struct _fluid_sequencer_client_t
/* API implementation */
/**
* Create a new sequencer object which uses the system timer. Use
* new_fluid_sequencer2() to specify whether the system timer or
* fluid_sequencer_process() is used to advance the sequencer.
* Create a new sequencer object which uses the system timer.
*
* @return New sequencer instance
*
* Use new_fluid_sequencer2() to specify whether the system timer or
* fluid_sequencer_process() is used to advance the sequencer.
*
* @deprecated As of fluidsynth 2.1.1 the use of the system timer has been deprecated.
*/
fluid_sequencer_t *
@ -96,12 +99,15 @@ new_fluid_sequencer(void)
/**
* Create a new sequencer object.
*
* @param use_system_timer If TRUE, sequencer will advance at the rate of the
* system clock. If FALSE, call fluid_sequencer_process() to advance
* the sequencer.
* @return New sequencer instance
* @since 1.1.0
*
* @note As of fluidsynth 2.1.1 the use of the system timer has been deprecated.
*
* @since 1.1.0
*/
fluid_sequencer_t *
new_fluid_sequencer2(int use_system_timer)
@ -142,8 +148,10 @@ new_fluid_sequencer2(int use_system_timer)
/**
* Free a sequencer object.
* @note Before fluidsynth 2.1.1 registered sequencer clients may not be fully freed by this function.
*
* @param seq Sequencer to delete
*
* @note Before fluidsynth 2.1.1 registered sequencer clients may not be fully freed by this function.
*/
void
delete_fluid_sequencer(fluid_sequencer_t *seq)
@ -165,10 +173,13 @@ delete_fluid_sequencer(fluid_sequencer_t *seq)
/**
* Check if a sequencer is using the system timer or not.
*
* @param seq Sequencer object
* @return TRUE if system timer is being used, FALSE otherwise.
* @since 1.1.0
*
* @deprecated As of fluidsynth 2.1.1 the usage of the system timer has been deprecated.
*
* @since 1.1.0
*/
int
fluid_sequencer_get_use_system_timer(fluid_sequencer_t *seq)
@ -183,6 +194,7 @@ fluid_sequencer_get_use_system_timer(fluid_sequencer_t *seq)
/**
* Register a sequencer client.
*
* @param seq Sequencer object
* @param name Name of sequencer client
* @param callback Sequencer client callback or NULL for a source client.
@ -235,9 +247,10 @@ fluid_sequencer_register_client(fluid_sequencer_t *seq, const char *name,
/**
* Unregister a previously registered client.
*
* The client's callback function will receive a FLUID_SEQ_UNREGISTERING event right before it is being unregistered.
* @param seq Sequencer object
* @param id Client ID as returned by fluid_sequencer_register_client().
*
* The client's callback function will receive a FLUID_SEQ_UNREGISTERING event right before it is being unregistered.
*/
void
fluid_sequencer_unregister_client(fluid_sequencer_t *seq, fluid_seq_id_t id)
@ -287,6 +300,7 @@ fluid_sequencer_unregister_client(fluid_sequencer_t *seq, fluid_seq_id_t id)
/**
* Count a sequencers registered clients.
*
* @param seq Sequencer object
* @return Count of sequencer clients.
*/
@ -303,6 +317,7 @@ fluid_sequencer_count_clients(fluid_sequencer_t *seq)
/**
* Get a client ID from its index (order in which it was registered).
*
* @param seq Sequencer object
* @param index Index of register client
* @return Client ID or #FLUID_FAILED if not found
@ -329,6 +344,7 @@ fluid_seq_id_t fluid_sequencer_get_client_id(fluid_sequencer_t *seq, int index)
/**
* Get the name of a registered client.
*
* @param seq Sequencer object
* @param id Client ID
* @return Client name or NULL if not found. String is internal and should not
@ -360,6 +376,7 @@ fluid_sequencer_get_client_name(fluid_sequencer_t *seq, fluid_seq_id_t id)
/**
* Check if a client is a destination client.
*
* @param seq Sequencer object
* @param id Client ID
* @return TRUE if client is a destination client, FALSE otherwise or if not found
@ -390,6 +407,7 @@ fluid_sequencer_client_is_dest(fluid_sequencer_t *seq, fluid_seq_id_t id)
/**
* Send an event immediately.
*
* @param seq Sequencer object
* @param evt Event to send (not copied, used directly)
*/
@ -434,6 +452,7 @@ fluid_sequencer_send_now(fluid_sequencer_t *seq, fluid_event_t *evt)
/**
* Schedule an event for sending at a later time.
*
* @param seq Sequencer object
* @param evt Event to send (will be copied into internal queue)
* @param time Time value in ticks (in milliseconds with the default time scale of 1000).
@ -479,6 +498,7 @@ fluid_sequencer_send_at(fluid_sequencer_t *seq, fluid_event_t *evt,
/**
* Remove events from the event queue.
*
* @param seq Sequencer object
* @param source Source client ID to match or -1 for wildcard
* @param dest Destination client ID to match or -1 for wildcard
@ -517,6 +537,7 @@ fluid_sequencer_get_tick_LOCAL(fluid_sequencer_t *seq, unsigned int cur_msec)
/**
* Get the current tick of the sequencer scaled by the time scale currently set.
*
* @param seq Sequencer object
* @return Current tick value
*/
@ -528,6 +549,7 @@ fluid_sequencer_get_tick(fluid_sequencer_t *seq)
/**
* Set the time scale of a sequencer.
*
* @param seq Sequencer object
* @param scale Sequencer scale value in ticks per second
* (default is 1000 for 1 tick per millisecond)
@ -563,6 +585,7 @@ fluid_sequencer_set_time_scale(fluid_sequencer_t *seq, double scale)
/**
* Get a sequencer's time scale.
*
* @param seq Sequencer object.
* @return Time scale value in ticks per second.
*/
@ -576,11 +599,13 @@ fluid_sequencer_get_time_scale(fluid_sequencer_t *seq)
/**
* Advance a sequencer.
*
* @param seq Sequencer object
* @param msec Time to advance sequencer to (absolute time since sequencer start).
*
* If you have registered the synthesizer as client (fluid_sequencer_register_fluidsynth()), the synth
* will take care of calling fluid_sequencer_process(). Otherwise it is up to the user to
* advance the sequencer manually.
* @param seq Sequencer object
* @param msec Time to advance sequencer to (absolute time since sequencer start).
*
* @since 1.1.0
*/
void

View file

@ -78,6 +78,10 @@ delete_fluid_seqbind(fluid_seqbind_t *seqbind)
/**
* Registers a synthesizer as a destination client of the given sequencer.
*
* @param seq Sequencer instance
* @param synth Synthesizer instance
* @returns Sequencer client ID, or #FLUID_FAILED on error.
*
* A convenience wrapper function around fluid_sequencer_register_client(), that allows you to
* easily process and render enqueued sequencer events with fluidsynth's synthesizer.
* The client being registered will be named @c fluidsynth.
@ -85,26 +89,23 @@ delete_fluid_seqbind(fluid_seqbind_t *seqbind)
* @note Implementations are encouraged to explicitly unregister this client either by calling
* fluid_sequencer_unregister_client() or by sending an unregistering event to the sequencer. Before
* fluidsynth 2.1.1 this was mandatory to avoid memory leaks.
@code{.cpp}
fluid_seq_id_t seqid = fluid_sequencer_register_fluidsynth(seq, synth);
// ... do work
fluid_event_t* evt = new_fluid_event();
fluid_event_set_source(evt, -1);
fluid_event_set_dest(evt, seqid);
fluid_event_unregistering(evt);
// unregister the "fluidsynth" client immediately
fluid_sequencer_send_now(seq, evt);
delete_fluid_event(evt);
delete_fluid_synth(synth);
delete_fluid_sequencer(seq);
@endcode
*
* @param seq Sequencer instance
* @param synth Synthesizer instance
* @returns Sequencer client ID, or #FLUID_FAILED on error.
* @code{.cpp}
* fluid_seq_id_t seqid = fluid_sequencer_register_fluidsynth(seq, synth);
*
* // ... do work
*
* fluid_event_t* evt = new_fluid_event();
* fluid_event_set_source(evt, -1);
* fluid_event_set_dest(evt, seqid);
* fluid_event_unregistering(evt);
*
* // unregister the "fluidsynth" client immediately
* fluid_sequencer_send_now(seq, evt);
* delete_fluid_event(evt);
* delete_fluid_synth(synth);
* delete_fluid_sequencer(seq);
* @endcode
*/
fluid_seq_id_t
fluid_sequencer_register_fluidsynth(fluid_sequencer_t *seq, fluid_synth_t *synth)
@ -352,12 +353,15 @@ static fluid_seq_id_t get_fluidsynth_dest(fluid_sequencer_t *seq)
}
/**
* Transforms an incoming midi event (from a midi driver or midi router) to a
* Transforms an incoming MIDI event (from a MIDI driver or MIDI router) to a
* sequencer event and adds it to the sequencer queue for sending as soon as possible.
* The signature of this function is of type #handle_midi_event_func_t.
*
* @param data The sequencer, must be a valid #fluid_sequencer_t
* @param event MIDI event
* @return #FLUID_OK or #FLUID_FAILED
*
* The signature of this function is of type #handle_midi_event_func_t.
*
* @since 1.1.0
*/
int

View file

@ -331,10 +331,11 @@ static int fluid_sffile_read_wav(SFData *sf, unsigned int start, unsigned int en
/**
* Check if a file is a SoundFont file.
*
* If fluidsynth was built with DLS support, this function will also identify DLS files.
* @param filename Path to the file to check
* @return TRUE if it could be a SF2, SF3 or DLS file, FALSE otherwise
*
* If fluidsynth was built with DLS support, this function will also identify DLS files.
*
* @note This function only checks whether header(s) in the RIFF chunk are present.
* A call to fluid_synth_sfload() might still fail.
*/

View file

@ -156,8 +156,6 @@ void *fluid_sfloader_get_data(fluid_sfloader_t *loader)
/**
* Set custom callbacks to be used upon soundfont loading.
*
* Useful for loading a soundfont from memory, see \a doc/fluidsynth_sfload_mem.c as an example.
*
* @param loader The SoundFont loader instance.
* @param open A function implementing #fluid_sfloader_callback_open_t.
* @param read A function implementing #fluid_sfloader_callback_read_t.
@ -165,6 +163,9 @@ void *fluid_sfloader_get_data(fluid_sfloader_t *loader)
* @param tell A function implementing #fluid_sfloader_callback_tell_t.
* @param close A function implementing #fluid_sfloader_callback_close_t.
* @return #FLUID_OK if the callbacks have been successfully set, #FLUID_FAILED otherwise.
*
* Useful for loading a soundfont from memory, see \a doc/fluidsynth_sfload_mem.c as an example.
*
*/
int fluid_sfloader_set_callbacks(fluid_sfloader_t *loader,
fluid_sfloader_callback_open_t open,
@ -196,6 +197,7 @@ int fluid_sfloader_set_callbacks(fluid_sfloader_t *loader,
/**
* Creates a new virtual SoundFont instance structure.
*
* @param get_name A function implementing #fluid_sfont_get_name_t.
* @param get_preset A function implementing #fluid_sfont_get_preset_t.
* @param iter_start A function implementing #fluid_sfont_iteration_start_t, or NULL if preset iteration not needed.
@ -285,8 +287,8 @@ const char *fluid_sfont_get_name(fluid_sfont_t *sfont)
}
/**
* Retrieve the preset assigned the a SoundFont instance
* for the given bank and preset number.
* Retrieve the preset assigned the a SoundFont instance for the given bank and preset number.
*
* @param sfont The SoundFont instance.
* @param bank bank number of the preset
* @param prenum program number of the preset
@ -300,6 +302,7 @@ fluid_preset_t *fluid_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenu
/**
* Starts / re-starts virtual preset iteration in a SoundFont.
*
* @param sfont Virtual SoundFont instance
*/
void fluid_sfont_iteration_start(fluid_sfont_t *sfont)
@ -329,10 +332,11 @@ fluid_preset_t *fluid_sfont_iteration_next(fluid_sfont_t *sfont)
/**
* Destroys a SoundFont instance created with new_fluid_sfont().
*
* Implements #fluid_sfont_free_t.
*
* @param sfont The SoundFont instance to destroy.
* @return Always returns 0.
*
* Implements #fluid_sfont_free_t.
*
*/
int delete_fluid_sfont(fluid_sfont_t *sfont)
{
@ -467,9 +471,10 @@ fluid_sfont_t *fluid_preset_get_sfont(fluid_preset_t *preset)
/**
* Destroys a SoundFont preset instance created with new_fluid_preset().
*
* @param preset The SoundFont preset instance to destroy.
*
* Implements #fluid_preset_free_t.
*
* @param preset The SoundFont preset instance to destroy.
*/
void delete_fluid_preset(fluid_preset_t *preset)
{
@ -480,6 +485,7 @@ void delete_fluid_preset(fluid_preset_t *preset)
/**
* Create a new sample instance.
*
* @return The sample on success, NULL otherwise.
*/
fluid_sample_t *
@ -502,6 +508,7 @@ new_fluid_sample()
/**
* Destroy a sample instance previously created with new_fluid_sample().
*
* @param sample The sample to destroy.
*/
void
@ -521,10 +528,10 @@ delete_fluid_sample(fluid_sample_t *sample)
/**
* Returns the size of the fluid_sample_t structure.
*
* Useful in low latency scenarios e.g. to allocate a pool of samples.
*
* @return Size of fluid_sample_t in bytes
*
* Useful in low latency scenarios e.g. to allocate a pool of samples.
*
* @note It is recommend to zero initialize the memory before using the object.
*
* @warning Do NOT allocate samples on the stack and assign them to a voice!
@ -536,6 +543,7 @@ size_t fluid_sample_sizeof()
/**
* Set the name of a SoundFont sample.
*
* @param sample SoundFont sample
* @param name Name to assign to sample (20 chars in length + zero terminator)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
@ -551,6 +559,7 @@ int fluid_sample_set_name(fluid_sample_t *sample, const char *name)
/**
* Assign sample data to a SoundFont sample.
*
* @param sample SoundFont sample
* @param data Buffer containing 16 bit (mono-)audio sample data
* @param data24 If not NULL, pointer to the least significant byte counterparts of each sample data point in order to create 24 bit audio samples

View file

@ -24,8 +24,10 @@
/**
* Clone the modulators destination, sources, flags and amount.
*
* @param mod the modulator to store the copy to
* @param src the source modulator to retrieve the information from
*
* @note The \c next member of \c mod will be left unchanged.
*/
void
@ -41,6 +43,7 @@ fluid_mod_clone(fluid_mod_t *mod, const fluid_mod_t *src)
/**
* Set a modulator's primary source controller and flags.
*
* @param mod The modulator instance
* @param src Modulator source (#fluid_mod_src or a MIDI controller number)
* @param flags Flags determining mapping function and whether the source
@ -56,6 +59,7 @@ fluid_mod_set_source1(fluid_mod_t *mod, int src, int flags)
/**
* Set a modulator's secondary source controller and flags.
*
* @param mod The modulator instance
* @param src Modulator source (#fluid_mod_src or a MIDI controller number)
* @param flags Flags determining mapping function and whether the source
@ -71,6 +75,7 @@ fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags)
/**
* Set the destination effect of a modulator.
*
* @param mod The modulator instance
* @param dest Destination generator (#fluid_gen_type)
*/
@ -82,6 +87,7 @@ fluid_mod_set_dest(fluid_mod_t *mod, int dest)
/**
* Set the scale amount of a modulator.
*
* @param mod The modulator instance
* @param amount Scale amount to assign
*/
@ -93,6 +99,7 @@ fluid_mod_set_amount(fluid_mod_t *mod, double amount)
/**
* Get the primary source value from a modulator.
*
* @param mod The modulator instance
* @return The primary source value (#fluid_mod_src or a MIDI CC controller value).
*/
@ -104,6 +111,7 @@ fluid_mod_get_source1(const fluid_mod_t *mod)
/**
* Get primary source flags from a modulator.
*
* @param mod The modulator instance
* @return The primary source flags (#fluid_mod_flags).
*/
@ -115,6 +123,7 @@ fluid_mod_get_flags1(const fluid_mod_t *mod)
/**
* Get the secondary source value from a modulator.
*
* @param mod The modulator instance
* @return The secondary source value (#fluid_mod_src or a MIDI CC controller value).
*/
@ -126,6 +135,7 @@ fluid_mod_get_source2(const fluid_mod_t *mod)
/**
* Get secondary source flags from a modulator.
*
* @param mod The modulator instance
* @return The secondary source flags (#fluid_mod_flags).
*/
@ -137,6 +147,7 @@ fluid_mod_get_flags2(const fluid_mod_t *mod)
/**
* Get destination effect from a modulator.
*
* @param mod The modulator instance
* @return Destination generator (#fluid_gen_type)
*/
@ -148,6 +159,7 @@ fluid_mod_get_dest(const fluid_mod_t *mod)
/**
* Get the scale amount from a modulator.
*
* @param mod The modulator instance
* @return Scale amount
*/
@ -466,6 +478,7 @@ fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice)
/**
* Create a new uninitialized modulator structure.
*
* @return New allocated modulator or NULL if out of memory
*/
fluid_mod_t *
@ -484,6 +497,7 @@ new_fluid_mod()
/**
* Free a modulator structure.
*
* @param mod Modulator to free
*/
void
@ -495,9 +509,9 @@ delete_fluid_mod(fluid_mod_t *mod)
/**
* Returns the size of the fluid_mod_t structure.
*
* Useful in low latency scenarios e.g. to allocate a modulator on the stack.
*
* @return Size of fluid_mod_t in bytes
*
* Useful in low latency scenarios e.g. to allocate a modulator on the stack.
*/
size_t fluid_mod_sizeof()
{
@ -518,13 +532,14 @@ fluid_mod_is_src1_none(const fluid_mod_t *mod)
/**
* Checks if modulators source other than CC source is invalid.
* (specs SF 2.01 7.4, 7.8, 8.2.1)
*
* @param mod, modulator.
* @param src1_select, source input selection to check.
* 1 to check src1 source.
* 0 to check src2 source.
* @return FALSE if selected modulator source other than cc is invalid, TRUE otherwise.
*
* (specs SF 2.01 7.4, 7.8, 8.2.1)
*/
static int
fluid_mod_check_non_cc_source(const fluid_mod_t *mod, unsigned char src1_select)
@ -556,6 +571,7 @@ fluid_mod_check_non_cc_source(const fluid_mod_t *mod, unsigned char src1_select)
/**
* Checks if modulator CC source is invalid (specs SF 2.01 7.4, 7.8, 8.2.1).
*
* @param mod, modulator.
* @src1_select, source input selection:
* 1 to check src1 source or
@ -599,6 +615,7 @@ fluid_mod_check_cc_source(const fluid_mod_t *mod, unsigned char src1_select)
/**
* Checks valid modulator sources (specs SF 2.01 7.4, 7.8, 8.2.1)
*
* @param mod, modulator.
* @param name,if not NULL, pointer on a string displayed as a warning.
* @return TRUE if modulator sources src1, src2 are valid, FALSE otherwise.
@ -677,6 +694,7 @@ int fluid_mod_check_sources(const fluid_mod_t *mod, char *name)
/**
* Checks if two modulators are identical in sources, flags and destination.
*
* @param mod1 First modulator
* @param mod2 Second modulator
* @return TRUE if identical, FALSE otherwise
@ -720,6 +738,7 @@ int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl)
/**
* Check if the modulator has the given destination.
*
* @param mod The modulator instance
* @param gen The destination generator of type #fluid_gen_type to check for
* @return TRUE if the modulator has the given destination, FALSE otherwise.

View file

@ -600,7 +600,7 @@ static FLUID_INLINE unsigned int fluid_synth_get_min_note_length_LOCAL(fluid_syn
* @note The @p settings parameter is used directly and should freed after
* the synth has been deleted. Further note that you may modify FluidSettings of the
* @p settings instance. However, only those FluidSettings marked as 'realtime' will
* affect the synth immediately.
* affect the synth immediately. See the \ref fluidsettings for more details.
*/
fluid_synth_t *
new_fluid_synth(fluid_settings_t *settings)
@ -3021,15 +3021,6 @@ fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id,
/**
* Pins all samples of the given preset.
*
* This function will attempt to pin all samples of the given preset and
* load them into memory, if they are currently unloaded. "To pin" in this
* context means preventing them from being unloaded by an upcoming channel
* prog change.
*
* @note This function is only useful if <code>synth.dynamic-sample-loading</code> is enabled.
* By default, dynamic-sample-loading is disabled and all samples are kept in memory.
* Furthermore, this is only useful for presets which support dynamic-sample-loading (currently,
* only preset loaded with the default soundfont loader do).
* @param synth FluidSynth instance
* @param sfont_id ID of a loaded SoundFont
* @param bank_num MIDI bank number
@ -3038,6 +3029,17 @@ fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id,
* into memory successfully. #FLUID_FAILED otherwise. Note that #FLUID_OK
* is returned, even if <code>synth.dynamic-sample-loading</code> is disabled or
* the preset doesn't support dynamic-sample-loading.
*
* This function will attempt to pin all samples of the given preset and
* load them into memory, if they are currently unloaded. "To pin" in this
* context means preventing them from being unloaded by an upcoming channel
* prog change.
*
* @note This function is only useful if \ref settings_synth_dynamic-sample-loading is enabled.
* By default, dynamic-sample-loading is disabled and all samples are kept in memory.
* Furthermore, this is only useful for presets which support dynamic-sample-loading (currently,
* only preset loaded with the default soundfont loader do).
*
* @since 2.2.0
*/
int
@ -3070,16 +3072,18 @@ fluid_synth_pin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int pre
/**
* Unpin all samples of the given preset.
*
* This function undoes the effect of fluid_synth_pin_preset(). If the preset is
* not currently used, its samples will be unloaded.
*
* @note Only useful for presets loaded with the default soundfont loader and
* only if <code>synth.dynamic-sample-loading</code> is enabled.
* @param synth FluidSynth instance
* @param sfont_id ID of a loaded SoundFont
* @param bank_num MIDI bank number
* @param preset_num MIDI program number
* @return #FLUID_OK if preset was found, #FLUID_FAILED otherwise
*
* This function undoes the effect of fluid_synth_pin_preset(). If the preset is
* not currently used, its samples will be unloaded.
*
* @note Only useful for presets loaded with the default soundfont loader and
* only if \ref settings_synth_dynamic-sample-loading is enabled.
*
* @since 2.2.0
*/
int
@ -3457,7 +3461,8 @@ fluid_synth_program_reset(fluid_synth_t *synth)
}
/**
* Synthesize a block of floating point audio to separate audio buffers (multichannel rendering). First effect channel used by reverb, second for chorus.
* Synthesize a block of floating point audio to separate audio buffers (multi-channel rendering).
*
* @param synth FluidSynth instance
* @param len Count of audio frames to synthesize
* @param left Array of float buffers to store left channel of planar audio (as many as \c synth.audio-channels buffers, each of \c len in size)
@ -3466,9 +3471,13 @@ fluid_synth_program_reset(fluid_synth_t *synth)
* @param fx_right Since 1.1.7: If not \c NULL, array of float buffers to store right effect channels (size: dito)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*
* First effect channel used by reverb, second for chorus.
*
* @note Should only be called from synthesis thread.
*
* @deprecated fluid_synth_nwrite_float() is deprecated and will be removed in a future release. It may continue to work or it may return #FLUID_FAILED in the future. Consider using the more powerful and flexible fluid_synth_process().
* @deprecated fluid_synth_nwrite_float() is deprecated and will be removed in a future release.
* It may continue to work or it may return #FLUID_FAILED in the future. Consider using the more
* powerful and flexible fluid_synth_process().
*
* Usage example:
* @code{.cpp}
@ -3480,14 +3489,17 @@ fluid_synth_program_reset(fluid_synth_t *synth)
// we need twice as many (mono-)buffers
channels *= 2;
// fluid_synth_nwrite_float renders planar audio, e.g. if synth.audio-channels==16: each midi channel gets rendered to its own stereo buffer, rather than having one buffer and interleaved PCM
// fluid_synth_nwrite_float renders planar audio, e.g. if synth.audio-channels==16:
// each midi channel gets rendered to its own stereo buffer, rather than having
// one buffer and interleaved PCM
float** mix_buf = new float*[channels];
for(int i = 0; i < channels; i++)
{
mix_buf[i] = new float[FramesToRender];
}
// retrieve number of (stereo) effect channels (internally hardcoded to reverb (first chan) and chrous (second chan))
// retrieve number of (stereo) effect channels (internally hardcoded to reverb (first chan)
// and chrous (second chan))
fluid_settings_getint(settings, "synth.effects-channels", &channels);
channels *= 2;
@ -3705,7 +3717,34 @@ static FLUID_INLINE void fluid_synth_mix_single_buffer(float *FLUID_RESTRICT out
}
/**
* @brief Synthesize floating point audio to stereo audio channels (implements the default interface #fluid_audio_func_t).
* Synthesize floating point audio to stereo audio channels
* (implements the default interface #fluid_audio_func_t).
*
* @param synth FluidSynth instance
*
* @param len Count of audio frames to synthesize and store in every single buffer provided by \p out and \p fx.
* Zero value is permitted, the function does nothing and return FLUID_OK.
*
* @param nfx Count of arrays in \c fx. Must be a multiple of 2 (because of stereo).
* and in the range <code>0 <= nfx/2 <= (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
* Note that zero value is valid and allows to skip mixing effects in all fx output buffers.
*
* @param fx Array of buffers to store effects audio to. Buffers may
* alias with buffers of \c out. Individual NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
*
* @param nout Count of arrays in \c out. Must be a multiple of 2
* (because of stereo) and in the range <code>0 <= nout/2 <= fluid_synth_count_audio_channels()</code>.
* Note that zero value is valid and allows to skip mixing dry audio in all out output buffers.
*
* @param out Array of buffers to store (dry) audio to. Buffers may
* alias with buffers of \c fx. Individual NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
*
* @return #FLUID_OK on success,
* #FLUID_FAILED otherwise,
* - <code>fx == NULL</code> while <code>nfx > 0</code>, or <code>out == NULL</code> while <code>nout > 0</code>.
* - \c nfx or \c nout not multiple of 2.
* - <code>len < 0</code>.
* - \c nfx or \c nout exceed the range explained above.
*
* Synthesize and <strong>mix</strong> audio to a given number of planar audio buffers.
* Therefore pass <code>nout = N*2</code> float buffers to \p out in order to render
@ -3753,26 +3792,6 @@ fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 1) % nfx ] = right_bu
*
* <code>k = chan % fluid_synth_count_effects_groups()</code>
*
* @param synth FluidSynth instance
* @param len Count of audio frames to synthesize and store in every single buffer provided by \p out and \p fx.
* Zero value is permitted, the function does nothing and return FLUID_OK.
* @param nfx Count of arrays in \c fx. Must be a multiple of 2 (because of stereo).
* and in the range <code>0 <= nfx/2 <= (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
Note that zero value is valid and allows to skip mixing effects in all fx output buffers.
* @param fx Array of buffers to store effects audio to. Buffers may
alias with buffers of \c out. Individual NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
* @param nout Count of arrays in \c out. Must be a multiple of 2
(because of stereo) and in the range <code>0 <= nout/2 <= fluid_synth_count_audio_channels()</code>.
Note that zero value is valid and allows to skip mixing dry audio in all out output buffers.
* @param out Array of buffers to store (dry) audio to. Buffers may
alias with buffers of \c fx. Individual NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
* @return #FLUID_OK on success,
* #FLUID_FAILED otherwise,
* - <code>fx == NULL</code> while <code>nfx > 0</code>, or <code>out == NULL</code> while <code>nout > 0</code>.
* - \c nfx or \c nout not multiple of 2.
* - <code>len < 0</code>.
* - \c nfx or \c nout exceed the range explained above.
*
* @parblock
* @note The owner of the sample buffers must zero them out before calling this
* function, because any synthesized audio is mixed (i.e. added) to the buffers.
@ -5484,6 +5503,7 @@ fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num)
/**
* Set reverb parameters.
*
* @param synth FluidSynth instance
* @param roomsize Reverb room size value (0.0-1.0)
* @param damping Reverb damping value (0.0-1.0)
@ -5503,7 +5523,10 @@ fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize, double damping,
}
/**
* Set reverb roomsize. See fluid_synth_set_reverb() for further info.
* Set reverb roomsize.
*
* @param synth FluidSynth instance
* @param roomsize Reverb room size value (0.0-1.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize)
@ -5512,7 +5535,10 @@ int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize)
}
/**
* Set reverb damping. See fluid_synth_set_reverb() for further info.
* Set reverb damping.
*
* @param synth FluidSynth instance
* @param damping Reverb damping value (0.0-1.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping)
@ -5521,7 +5547,10 @@ int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping)
}
/**
* Set reverb width. See fluid_synth_set_reverb() for further info.
* Set reverb width.
*
* @param synth FluidSynth instance
* @param width Reverb width value (0.0-100.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width)
@ -5530,7 +5559,10 @@ int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width)
}
/**
* Set reverb level. See fluid_synth_set_reverb() for further info.
* Set reverb level.
*
* @param synth FluidSynth instance
* @param level Reverb level value (0.0-1.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level)
@ -5540,6 +5572,7 @@ int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level)
/**
* Set one or more reverb parameters.
*
* @param synth FluidSynth instance
* @param set Flags indicating which parameters should be set (#fluid_revmodel_set_t)
* @param roomsize Reverb room size value (0.0-1.2)
@ -5680,8 +5713,8 @@ fluid_synth_set_chorus_on(fluid_synth_t *synth, int on)
}
/**
* Set chorus parameters. It should be turned on with fluid_synth_set_chorus_on().
* Keep in mind, that the needed CPU time is proportional to 'nr'.
* Set chorus parameters.
*
* @param synth FluidSynth instance
* @param nr Chorus voice count (0-99, CPU time consumption proportional to
* this value)
@ -5691,6 +5724,9 @@ fluid_synth_set_chorus_on(fluid_synth_t *synth, int on)
* 0.0-21.0 is safe for sample-rate values up to 96KHz)
* @param type Chorus waveform type (#fluid_chorus_mod)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*
* It should be turned on with fluid_synth_set_chorus_on().
* Keep in mind, that the needed CPU time is proportional to 'nr'.
*/
int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
double speed, double depth_ms, int type)
@ -5700,7 +5736,11 @@ int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
}
/**
* Set the chorus voice count. See fluid_synth_set_chorus() for further info.
* Set the chorus voice count.
*
* @param synth FluidSynth instance
* @param nr Chorus voice count (0-99, CPU time consumption proportional to
* this value)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr)
@ -5709,7 +5749,10 @@ int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr)
}
/**
* Set the chorus level. See fluid_synth_set_chorus() for further info.
* Set the chorus level.
*
* @param synth FluidSynth instance
* @param level Chorus level (0.0-10.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level)
@ -5718,7 +5761,10 @@ int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level)
}
/**
* Set the chorus speed. See fluid_synth_set_chorus() for further info.
* Set the chorus speed.
*
* @param synth FluidSynth instance
* @param speed Chorus speed in Hz (0.1-5.0)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed)
@ -5727,7 +5773,11 @@ int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed)
}
/**
* Set the chorus depth. See fluid_synth_set_chorus() for further info.
* Set the chorus depth.
*
* @param synth FluidSynth instance
* @param depth_ms Chorus depth (max value depends on synth sample-rate,
* 0.0-21.0 is safe for sample-rate values up to 96KHz)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms)
@ -5736,7 +5786,10 @@ int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms)
}
/**
* Set the chorus type. See fluid_synth_set_chorus() for further info.
* Set the chorus type.
*
* @param synth FluidSynth instance
* @param type Chorus waveform type (#fluid_chorus_mod)
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*/
int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type)
@ -6934,14 +6987,13 @@ fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
/**
* Configure a general-purpose IIR biquad filter.
*
* This is an optional, additional filter that operates independently from the default low-pass filter required by the Soundfont2 standard.
* By default this filter is off (#FLUID_IIR_DISABLED).
*
* @param synth FluidSynth instance
* @param type Type of the IIR filter to use (see #fluid_iir_filter_type)
* @param flags Additional flags to customize this filter or zero to stay with the default (see #fluid_iir_filter_flags)
*
* @return #FLUID_OK if the settings have been successfully applied, otherwise #FLUID_FAILED
*
* This is an optional, additional filter that operates independently from the default low-pass filter required by the Soundfont2 standard.
* By default this filter is off (#FLUID_IIR_DISABLED).
*/
int fluid_synth_set_custom_filter(fluid_synth_t *synth, int type, int flags)
{
@ -7047,7 +7099,7 @@ static void fluid_synth_handle_important_channels(void *data, const char *name,
}
/** API legato mode *********************************************************/
/* API legato mode *********************************************************/
/**
* Sets the legato mode of a channel.
@ -7100,7 +7152,7 @@ int fluid_synth_get_legato_mode(fluid_synth_t *synth, int chan, int *legatomode)
FLUID_API_RETURN(FLUID_OK);
}
/** API portamento mode *********************************************************/
/* API portamento mode *********************************************************/
/**
* Sets the portamento mode of a channel.
@ -7153,7 +7205,7 @@ int fluid_synth_get_portamento_mode(fluid_synth_t *synth, int chan,
FLUID_API_RETURN(FLUID_OK);
}
/** API breath mode *********************************************************/
/* API breath mode *********************************************************/
/**
* Sets the breath mode of a channel.

View file

@ -367,6 +367,7 @@ fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample,
/**
* Update sample rate.
*
* @note If the voice is active, it will be turned off.
*/
void
@ -385,6 +386,7 @@ fluid_voice_set_output_rate(fluid_voice_t *voice, fluid_real_t value)
/**
* Set the value of a generator.
*
* @param voice Voice instance
* @param i Generator ID (#fluid_gen_type)
* @param val Generator value
@ -403,6 +405,7 @@ fluid_voice_gen_set(fluid_voice_t *voice, int i, float val)
/**
* Offset the value of a generator.
*
* @param voice Voice instance
* @param i Generator ID (#fluid_gen_type)
* @param val Value to add to the existing value
@ -416,6 +419,7 @@ fluid_voice_gen_incr(fluid_voice_t *voice, int i, float val)
/**
* Get the value of a generator.
*
* @param voice Voice instance
* @param gen Generator ID (#fluid_gen_type)
* @return Current generator value
@ -734,13 +738,14 @@ calculate_hold_decay_buffers(fluid_voice_t *voice, int gen_base,
* NRPN system. fluid_voice_gen_value(voice, generator_enumerator) returns the sum
* of all three.
*/
/**
* Update all the synthesis parameters, which depend on generator \a gen.
* Update all the synthesis parameters which depend on generator \a gen.
*
* @param voice Voice instance
* @param gen Generator id (#fluid_gen_type)
*
* This is only necessary after changing a generator of an already operating voice.
* Most applications will not need this function.
* Calling this function is only necessary after changing a generator of an already playing voice.
*/
void
fluid_voice_update_param(fluid_voice_t *voice, int gen)
@ -1140,6 +1145,7 @@ fluid_voice_update_param(fluid_voice_t *voice, int gen)
/**
* Recalculate voice parameters for a given control.
*
* @param voice the synthesis voice
* @param cc flag to distinguish between a continuous control and a channel control (pitch bend, ...)
* @param ctrl the control number:
@ -1236,17 +1242,18 @@ int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl)
}
/**
* Update all the modulators. This function is called after a
* ALL_CTRL_OFF MIDI message has been received (CC 121).
* Update all the modulators.
*
* All destination of all modulators must be updated.
* This function is called after a ALL_CTRL_OFF MIDI message has been received (CC 121).
* All destinations of all modulators will be updated.
*/
int fluid_voice_modulate_all(fluid_voice_t *voice)
{
return fluid_voice_modulate(voice, 0, -1);
}
/** legato update functions --------------------------------------------------*/
/* legato update functions --------------------------------------------------*/
/* Updates voice portamento parameters
*
* @voice voice the synthesis voice
@ -1456,6 +1463,7 @@ fluid_voice_stop(fluid_voice_t *voice)
/**
* Adds a modulator to the voice if the modulator has valid sources.
*
* @param voice Voice instance.
* @param mod Modulator info (copied).
* @param mode Determines how to handle an existing identical modulator.
@ -1543,15 +1551,16 @@ fluid_voice_add_mod_local(fluid_voice_t *voice, fluid_mod_t *mod, int mode, int
/**
* Get the unique ID of the noteon-event.
*
* @param voice Voice instance
* @return Note on unique ID
*
* A SoundFont loader may store the voice processes it has created for
* A SoundFont loader may store pointers to voices it has created for
* real-time control during the operation of a voice (for example: parameter
* changes in SoundFont editor). The synth uses a pool of voices, which are
* changes in SoundFont editor). The synth uses a pool of voices internally which are
* 'recycled' and never deallocated.
*
* Before modifying an existing voice, check
* However, before modifying an existing voice, check
* - that its state is still 'playing'
* - that the ID is still the same
*
@ -1563,9 +1572,13 @@ unsigned int fluid_voice_get_id(const fluid_voice_t *voice)
}
/**
* Check if a voice is producing sound. This is also true after a voice received a noteoff as it may be playing in release phase.
* Check if a voice is producing sound.
*
* @param voice Voice instance
* @return TRUE if playing, FALSE otherwise
*
* This might also return TRUE after the voice received a noteoff event, as it may
* still be playing in release phase.
*/
int fluid_voice_is_playing(const fluid_voice_t *voice)
{
@ -1576,9 +1589,13 @@ int fluid_voice_is_playing(const fluid_voice_t *voice)
}
/**
* Check if a voice is ON. A voice is ON, if it has not yet received a noteoff event.
* Check if a voice is ON.
*
* @param voice Voice instance
* @return TRUE if on, FALSE otherwise
*
* A voice is ON if it has not yet received a noteoff event.
*
* @since 1.1.7
*/
int fluid_voice_is_on(const fluid_voice_t *voice)
@ -1588,8 +1605,10 @@ int fluid_voice_is_on(const fluid_voice_t *voice)
/**
* Check if a voice keeps playing after it has received a noteoff due to being held by sustain.
*
* @param voice Voice instance
* @return TRUE if sustained, FALSE otherwise
*
* @since 1.1.7
*/
int fluid_voice_is_sustained(const fluid_voice_t *voice)
@ -1599,8 +1618,10 @@ int fluid_voice_is_sustained(const fluid_voice_t *voice)
/**
* Check if a voice keeps playing after it has received a noteoff due to being held by sostenuto.
*
* @param voice Voice instance
* @return TRUE if sostenuto, FALSE otherwise
*
* @since 1.1.7
*/
int fluid_voice_is_sostenuto(const fluid_voice_t *voice)
@ -1609,9 +1630,13 @@ int fluid_voice_is_sostenuto(const fluid_voice_t *voice)
}
/**
* If the voice is playing, gets the midi channel the voice is playing on. Else the result is undefined.
* Return the MIDI channel the voice is playing on.
*
* @param voice Voice instance
* @return The channel assigned to this voice
*
* @note The result of this function is only valid if the voice is playing.
*
* @since 1.1.7
*/
int fluid_voice_get_channel(const fluid_voice_t *voice)
@ -1620,11 +1645,16 @@ int fluid_voice_get_channel(const fluid_voice_t *voice)
}
/**
* If the voice is playing, gets the midi key the voice is actually playing at. Else the result is undefined.
* If the voice was started from an instrument which uses a fixed key generator, it returns that.
* Else returns the same as \c fluid_voice_get_key.
* Return the effective MIDI key of the playing voice.
*
* @param voice Voice instance
* @return The midi key this voice is playing at
* @return The MIDI key this voice is playing at
*
* If the voice was started from an instrument which uses a fixed key generator, it returns that.
* Otherwise returns the same value as \c fluid_voice_get_key.
*
* @note The result of this function is only valid if the voice is playing.
*
* @since 1.1.7
*/
int fluid_voice_get_actual_key(const fluid_voice_t *voice)
@ -1642,10 +1672,13 @@ int fluid_voice_get_actual_key(const fluid_voice_t *voice)
}
/**
* If the voice is playing, gets the midi key from the noteon event, by which the voice was initially turned on with.
* Else the result is undefined.
* Return the MIDI key from the starting noteon event.
*
* @param voice Voice instance
* @return The midi key of the noteon event that originally turned on this voice
* @return The MIDI key of the noteon event that originally turned on this voice
*
* @note The result of this function is only valid if the voice is playing.
*
* @since 1.1.7
*/
int fluid_voice_get_key(const fluid_voice_t *voice)
@ -1654,11 +1687,16 @@ int fluid_voice_get_key(const fluid_voice_t *voice)
}
/**
* If the voice is playing, gets the midi velocity the voice is actually playing at. Else the result is undefined.
* If the voice was started from an instrument which uses a fixed velocity generator, it returns that.
* Else returns the same as \c fluid_voice_get_velocity.
* Return the effective MIDI velocity of the playing voice.
*
* @param voice Voice instance
* @return The midi velocity this voice is playing at
* @return The MIDI velocity this voice is playing at
*
* If the voice was started from an instrument which uses a fixed velocity generator, it returns that.
* Otherwise it returns the same value as \c fluid_voice_get_velocity.
*
* @note The result of this function is only valid if the voice is playing.
*
* @since 1.1.7
*/
int fluid_voice_get_actual_velocity(const fluid_voice_t *voice)
@ -1676,10 +1714,13 @@ int fluid_voice_get_actual_velocity(const fluid_voice_t *voice)
}
/**
* If the voice is playing, gets the midi velocity from the noteon event, by which the voice was initially
* turned on with. Else the result is undefined.
* Return the MIDI velocity from the starting noteon event.
*
* @param voice Voice instance
* @return The midi velocity which originally turned on this voice
* @return The MIDI velocity which originally turned on this voice
*
* @note The result of this function is only valid if the voice is playing.
*
* @since 1.1.7
*/
int fluid_voice_get_velocity(const fluid_voice_t *voice)
@ -1819,8 +1860,10 @@ int fluid_voice_set_gain(fluid_voice_t *voice, fluid_real_t gain)
* - Calculate, what factor will make the loop inaudible
* - Store in sample
*/
/**
* Calculate the peak volume of a sample for voice off optimization.
*
* @param s Sample to optimize
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
*

View file

@ -255,6 +255,7 @@ delete_fluid_set_setting(fluid_setting_node_t *node)
/**
* Create a new settings object
*
* @return the pointer to the settings object
*/
fluid_settings_t *
@ -278,6 +279,7 @@ new_fluid_settings(void)
/**
* Delete the provided settings object
*
* @param settings a settings object
*/
void
@ -1015,15 +1017,17 @@ error_recovery:
/**
* Copy the value of a string setting into the provided buffer (thread safe)
*
* @param settings a settings object
* @param name a setting's name
* @param str Caller supplied buffer to copy string value to
* @param len Size of 'str' buffer (no more than len bytes will be written, which
* will always include a zero terminator)
* @return #FLUID_OK if the value exists, #FLUID_FAILED otherwise
* @since 1.1.0
*
* @note A size of 256 should be more than sufficient for the string buffer.
*
* @since 1.1.0
*/
int
fluid_settings_copystr(fluid_settings_t *settings, const char *name,
@ -1075,14 +1079,16 @@ fluid_settings_copystr(fluid_settings_t *settings, const char *name,
/**
* Duplicate the value of a string setting
*
* @param settings a settings object
* @param name a setting's name
* @param str Location to store pointer to allocated duplicate string
* @return #FLUID_OK if the value exists and was successfully duplicated, #FLUID_FAILED otherwise
* @since 1.1.0
*
* Like fluid_settings_copystr() but allocates a new copy of the string. Caller
* owns the string and should free it with fluid_free() when done using it.
*
* @since 1.1.0
*/
int
fluid_settings_dupstr(fluid_settings_t *settings, const char *name, char **str)
@ -1194,13 +1200,14 @@ fluid_settings_str_equal(fluid_settings_t *settings, const char *name, const cha
}
/**
* Get the default value of a string setting. Note that the returned string is
* not owned by the caller and should not be modified or freed.
* Get the default value of a string setting.
*
* @param settings a settings object
* @param name a setting's name
* @param def the default string value of the setting if it exists
* @return FLUID_OK on success, FLUID_FAILED otherwise
*
* @note The returned string is* not owned by the caller and should not be modified or freed.
*/
int
fluid_settings_getstr_default(fluid_settings_t *settings, const char *name, char **def)
@ -1240,6 +1247,7 @@ fluid_settings_getstr_default(fluid_settings_t *settings, const char *name, char
/**
* Add an option to a string setting (like an enumeration value).
*
* @param settings a settings object
* @param name a setting's name
* @param s option string to add
@ -1277,6 +1285,7 @@ fluid_settings_add_option(fluid_settings_t *settings, const char *name, const ch
/**
* Remove an option previously assigned by fluid_settings_add_option().
*
* @param settings a settings object
* @param name a setting's name
* @param s option string to remove
@ -1602,6 +1611,7 @@ fluid_settings_getint(fluid_settings_t *settings, const char *name, int *val)
/**
* Get the range of values of an integer setting
*
* @param settings a settings object
* @param name a setting's name
* @param min setting's range lower limit
@ -1727,10 +1737,12 @@ fluid_settings_foreach_option(fluid_settings_t *settings, const char *name,
/**
* Count option string values for a string setting.
*
* @param settings a settings object
* @param name Name of setting
* @return Count of options for this string setting (0 if none, -1 if not found
* or not a string setting)
*
* @since 1.1.0
*/
int
@ -1758,11 +1770,13 @@ fluid_settings_option_count(fluid_settings_t *settings, const char *name)
/**
* Concatenate options for a string setting together with a separator between.
*
* @param settings Settings object
* @param name Settings name
* @param separator String to use between options (NULL to use ", ")
* @return Newly allocated string or NULL on error (out of memory, not a valid
* setting \p name or not a string setting). Free the string when finished with it by using fluid_free().
*
* @since 1.1.0
*/
char *

View file

@ -219,8 +219,15 @@ void* fluid_alloc(size_t len)
/**
* Convenience wrapper for free() that satisfies at least C90 requirements.
* Especially useful when using fluidsynth with programming languages that do not provide malloc() and free().
* @note Only use this function when the API documentation explicitly says so. Otherwise use adequate \c delete_fluid_* functions.
*
* @param ptr Pointer to memory region that should be freed
*
* Especially useful when using fluidsynth with programming languages that do not
* provide malloc() and free().
*
* @note Only use this function when the API documentation explicitly says so. Otherwise use
* adequate \c delete_fluid_* functions.
*
* @since 2.0.7
*/
void fluid_free(void* ptr)