Merge pull request #459 from redtide/moved-scripts
Move Doxygen scripts
This commit is contained in:
commit
e8d052d50c
12 changed files with 186 additions and 760 deletions
11
.travis.yml
11
.travis.yml
|
|
@ -166,17 +166,6 @@ jobs:
|
|||
install: sudo pip install git-archive-all
|
||||
script: git-archive-all --prefix="sfizz-${TRAVIS_BRANCH}/" -9 "${INSTALL_DIR}.tar.gz"
|
||||
|
||||
- name: "Generate documentation"
|
||||
if: (tag IS present) AND (branch = master) AND (type = push)
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- doxygen
|
||||
- cmake
|
||||
- libsndfile-dev
|
||||
install: skip
|
||||
script: .travis/update_dox.sh
|
||||
|
||||
- name: "Discord Webhook"
|
||||
install: skip
|
||||
script: bash ${TRAVIS_BUILD_DIR}/.travis/discord_webhook.sh success
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -x # No fail, we need to go back to the original branch at the end
|
||||
. .travis/environment.sh
|
||||
|
||||
mkdir build && cd build && cmake -DSFIZZ_JACK=OFF -DSFIZZ_SHARED=OFF -DSFIZZ_LV2=OFF .. && cd ..
|
||||
doxygen Doxyfile
|
||||
./doxygen/scripts/generate_api_index.sh
|
||||
git fetch --depth=1 https://github.com/${TRAVIS_REPO_SLUG}.git refs/heads/gh-pages:refs/remotes/origin/gh-pages
|
||||
git checkout origin/gh-pages
|
||||
git checkout -b gh-pages
|
||||
mv _api api/${TRAVIS_TAG}
|
||||
mv api_index.md api/index.md
|
||||
git add api && git commit -m "Release ${TRAVIS_TAG} (Travis build: ${TRAVIS_BUILD_NUMBER})"
|
||||
git remote add origin-pages https://${GITHUB_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git > /dev/null 2>&1
|
||||
git push --quiet --set-upstream origin-pages gh-pages
|
||||
git checkout ${TRAVIS_BRANCH}
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
<doxygenlayout version="1.0">
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="no" title=""/>
|
||||
<tab type="pages" visible="yes" title="" intro=""/>
|
||||
<tab type="modules" visible="yes" title="Categories" intro=""/>
|
||||
<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="no"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<membergroups visible="yes"/>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes 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=""/>
|
||||
</memberdecl>
|
||||
<allmemberslink visible="yes"/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="no"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<membergroups visible="yes"/>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdecl>
|
||||
<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="no"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<membergroups visible="yes"/>
|
||||
<classes visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdecl>
|
||||
<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="no"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<membergroups visible="yes"/>
|
||||
<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=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdecl>
|
||||
<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"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
</directory>
|
||||
</doxygenlayout>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<hr>
|
||||
<footer>
|
||||
<p style="text-align:left">Copyright © 2019-2020 Paul Ferrand
|
||||
<span style="float:right">Generated for sfizz by
|
||||
<a href="http://www.doxygen.org/index.html"
|
||||
target="_new">Doxygen</a> $doxygenversion</span>
|
||||
</p>
|
||||
</footer>
|
||||
</div><!-- container -->
|
||||
<script src="/sfizz/assets/js/scripts.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Home - sfizz</title>
|
||||
|
||||
<meta name="author" content="Paul Ferrand">
|
||||
<meta name="web-author" content="Andrea Zanellato">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!-- Atom Feeds -->
|
||||
<link href="/sfizz/atom.xml" rel="alternate" title="News"
|
||||
type="application/atom+xml" />
|
||||
|
||||
<!-- Favicon Generator Icons -->
|
||||
<link rel="apple-touch-icon" sizes="180x180"
|
||||
href="/sfizz/assets/ico/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/sfizz/assets/ico/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/sfizz/assets/ico/favicon-16x16.png">
|
||||
<link rel="manifest" href="/sfizz/assets/ico/site.webmanifest">
|
||||
<link rel="mask-icon" href="/sfizz/assets/ico/safari-pinned-tab.svg"
|
||||
color="#5bbad5">
|
||||
<link rel="shortcut icon" href="/sfizz/assets/ico/favicon.ico">
|
||||
<meta name="msapplication-TileColor"
|
||||
content="#da532c">
|
||||
<meta name="msapplication-config" content="/sfizz/assets/ico/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link href="$relpath$tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath$jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath$dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath$$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
<!-- Stylesheets -->
|
||||
<link href="/sfizz/assets/css/style.min.css"
|
||||
rel="stylesheet" media="screen">
|
||||
|
||||
<!-- Font Awesome Icons -->
|
||||
<script src="https://kit.fontawesome.com/8d25d19870.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<button onclick="topFunction()" id="scrollButton" title="Go to top">Top</button>
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark" style="background-color:#222">
|
||||
<a class="navbar-brand" href="/sfizz/">
|
||||
<img src="/sfizz/assets/img/logo.png"
|
||||
width="30" height="30" class="d-inline-block" alt="">
|
||||
sfizz</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
||||
data-target="#navbarContent" aria-controls="navbarContent"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarContent">
|
||||
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">
|
||||
<i class="fas fa-home fa-fw" aria-hidden="true"></i>
|
||||
Home</a>
|
||||
</li>
|
||||
|
||||
<!-- FIXME: Dropdown buttons are shown but menus are broken for some reason
|
||||
(not the container div)
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#"
|
||||
id="navbarProjects" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-hammer fa-fw" aria-hidden="true"></i>
|
||||
Projects</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarProjects">
|
||||
<a class="dropdown-item"
|
||||
href="/beatbox/">
|
||||
<i class="fas fa-drum fa-fw" aria-hidden="true"></i>
|
||||
BeatBox</a>
|
||||
<a class="dropdown-item disabled"
|
||||
href="/sfizz/">
|
||||
<i class="fas fa-play-circle fa-fw" aria-hidden="true"></i>
|
||||
sfizz</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/sfizz-render/">
|
||||
sfizz-render</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/sfz-flat/">
|
||||
sfz-flat</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/sfz-opcode-checker/">
|
||||
sfz-opcode-checker</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/emacs-sfz-mode/">
|
||||
Emacs Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/syntax-highlighting-gedit/">
|
||||
gedit Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/syntax-highlighting-geany/">
|
||||
Geany Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/syntax-highlighting-sublime-text/">
|
||||
Sublime Text Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/sfz.vim">
|
||||
Vim Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/syntax-highlighting-vscode/">
|
||||
VSCode Syntax Highlight</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#"
|
||||
id="navbarDocumentation" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-book fa-fw" aria-hidden="true"></i>
|
||||
Documentation</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDocumentation">
|
||||
<a class="dropdown-item"
|
||||
href="/sfizz/api"><i class="fas fa-code fa-fw" aria-hidden="true"></i>
|
||||
API</a>
|
||||
<a class="dropdown-item"
|
||||
href="/sfizz/development/build">
|
||||
<i class="fas fa-code fa-fw" aria-hidden="true"></i>
|
||||
Build</a>
|
||||
<a class="dropdown-item"
|
||||
href="/sfizz/development/status">
|
||||
<i class="fas fa-tasks fa-fw" aria-hidden="true"></i>
|
||||
SFZ Opcodes</a>
|
||||
</div>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sfizz/downloads">
|
||||
<i class="fas fa-download fa-fw" aria-hidden="true"></i>
|
||||
Download</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sfizz/search/">
|
||||
<i class="fas fa-search fa-fw" aria-hidden="true"></i>
|
||||
Search</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
$searchbox
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</nav>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
|
@ -1,198 +0,0 @@
|
|||
#page_container {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: auto !important;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
div.contents, div.searchresults {
|
||||
margin-top: 10px;
|
||||
margin-right: 12px;
|
||||
padding-bottom: 70px;
|
||||
}
|
||||
|
||||
#projectlogo {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#projectnumber {
|
||||
font-size: 120%;
|
||||
font-family: Tahoma, Arial, sans-serif;
|
||||
text-align: right;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
font-size: 14px;
|
||||
}
|
||||
.tabs2, .tabs3 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.navpath ul {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #002D88;
|
||||
font-weight: normal;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 150%;
|
||||
border-bottom: 1px solid #3276FF;
|
||||
}
|
||||
h2 {
|
||||
font-size: 135%;
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 120%;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 100%;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
div.headertitle h1 {
|
||||
margin: 10px 2px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.toc h3 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
div.toc li {
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
padding-left: 14px;
|
||||
}
|
||||
|
||||
img.logo {
|
||||
float: right;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
div.logo {
|
||||
float: right;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
table.directory {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.icon {
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
div.appearance {
|
||||
margin: 1em 0em;
|
||||
}
|
||||
div.appearance table {
|
||||
margin: 0.5em 0em;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
div.appearance img {
|
||||
margin: 0.5em;
|
||||
}
|
||||
div.appearance .caption {
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.appearance_brief table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
text-align: center;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
div.appearance_brief table td:first-child {
|
||||
width: 20em;
|
||||
text-align: left;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
div.appearance_brief table td {
|
||||
border-style: none solid solid none;
|
||||
border-width: 1px;
|
||||
border-color: lightblue;
|
||||
}
|
||||
|
||||
|
||||
td.green { color: green; }
|
||||
td.orange { color: #ff8000; }
|
||||
td.red { color: red; }
|
||||
|
||||
span.literal {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-family: monospace, fixed;
|
||||
}
|
||||
|
||||
/* we make all the following <span> tags render the text just like
|
||||
the standard Doxygen @remarks, @see tags do, to obtain a uniform
|
||||
look and feel */
|
||||
span.itemdef, span.lib, span.category, span.stdobj, span.styles,
|
||||
span.events, span.flags, span.appearance, span.impl, span.avail {
|
||||
font-weight: bold;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
span.style, span.event, span.flag {
|
||||
font-weight: bold;
|
||||
color: #880000;
|
||||
}
|
||||
|
||||
div.styleDesc, div.eventDesc, div.flagDesc {
|
||||
margin-left: 3%;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
div.eventHandler {
|
||||
margin: 1em;
|
||||
text-indent: 3%;
|
||||
}
|
||||
|
||||
div.eventHandler span {
|
||||
padding: 5px;
|
||||
background-color: #eeeeee;
|
||||
font-family: monospace, fixed;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 110%;
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
address.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
padding: 10px 0;
|
||||
width: 100%;
|
||||
border-top: 1px solid #0043CC;
|
||||
background-image: url('nav_h.png');
|
||||
background-repeat: repeat-x;
|
||||
background-color: #F4F8FF;
|
||||
}
|
||||
|
||||
address.footer small {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
# Global view of the engine
|
||||
|
||||
The sfizz engine is basically a "Synth" object that takes an SFZ file in, receives MIDI-type events
|
||||
and is able to render audio through successive calls to a callback function. This is in line with
|
||||
the way most audio applications and plugins are working. A high-level overview is presented in the
|
||||
following diagram.
|
||||
|
||||
```
|
||||
C and C++ API entry point
|
||||
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
+--------v-------+
|
||||
| |
|
||||
+-------------------------- Synth -----------------------------+
|
||||
| | | |
|
||||
| +----------------+ |
|
||||
| | |
|
||||
+--------v------+ | +---------v--------+
|
||||
| | +---------v---------+ | |
|
||||
| Region list | | Common resources | | Voice pool |
|
||||
| | | and state | | |
|
||||
+---------------+ | ----------------- | +------------------+
|
||||
Built from the SFZ file | File pool |
|
||||
| Envelope pool | The voices are the polyphony
|
||||
Each region is a semi-passive | LFO pool | of the synth. They are idle
|
||||
description object that can | Buffer pool | and they get activated by the
|
||||
decide whether it is "active" | Midi state | synth to play a region on a
|
||||
or not depending on the chain | ... | specific event. They are then
|
||||
of MIDI events it receives. +-------------------+ "linked" to the region while
|
||||
Once activated, a voice is There are a number of common it is played, and reset to
|
||||
chosen to play the region until resources that are needed for their idle state when they
|
||||
it ends naturally or through all the regions and in parti- are done playing the region.
|
||||
note-offs or off-groups. cular the voices. This includes
|
||||
all the (preloaded) files for
|
||||
the SFZ instrument, but will
|
||||
include in the future the EG
|
||||
and LFOs that are needed to
|
||||
achieve compliance with the
|
||||
SFZ v2 specification. This will
|
||||
also include a temporary buffer
|
||||
holder that voices may share.
|
||||
A common resource of importance
|
||||
is the MIDI state: note durations
|
||||
are needed for some opcodes --
|
||||
for example rt_decay -- and
|
||||
triggering velocities too.
|
||||
```
|
||||
|
||||
The Synth, Voices and Regions form the bulk of the code complexity. The rest of the engine is dedicated of
|
||||
mostly helper classes to enable easy management of floating-point buffers in which the audio data is held,
|
||||
signal processing and accelerated (SIMD) computations, and abstractions that are specific to the SFZ format
|
||||
such as envelope generators, curves or LFOs.
|
||||
|
||||
# Parsing the SFZ files
|
||||
|
||||
The sfz file logic is pretty simple and well defined. The sfzformat.com website contains an extensive documentation
|
||||
on it. At its core, an SFZ file describes a list of `region` objects on which a certain number of "opcodes" will
|
||||
apply. Opcodes can determine the sample played, the event conditions that will trigger the sample such as the range
|
||||
of notes, channels, velocities, the processing to apply on the sample while playing, and many more things. It is
|
||||
also possible to describe a `group` of regions, as well as exclusive groups that will shut off other regions that may
|
||||
already be playing. There are also `master` groups, and `global` opcodes and some other types.
|
||||
|
||||
All the opcodes are declared within a header, in a pseudo-xml markup language that looks like this
|
||||
```sfz
|
||||
<global> volume=6
|
||||
<control> set_cc4=5
|
||||
<region> key=36 sample=kick.wav
|
||||
```
|
||||
Here we have 3 headers (`global`, `control` and `region`) and each header holds some opcodes. All of these opcodes
|
||||
have a value---for example the volume is equal to 6 in the `global` header. Some opcodes also have parameters.
|
||||
The `control` header holds an opcode `set_cc` with the parameter `4` and value `5`. The parameter here is the CC to set,
|
||||
and the value at which to set it is 5.
|
||||
|
||||
The parsing logic of sfizz is handled through a base class called Parser---a very original choice. This parser has
|
||||
a virtual callback that gets called whenever a header description is "complete", along with a list of opcodes that
|
||||
apply to the header. Subclassing the Parser then allows to build different SFZ handlers, from full-blown synths as
|
||||
with sfizz to simpler things such as printers (see in particular https://github.com/sfztools/sfz-flat/). If we look
|
||||
at the core of the latter example, it will look something like the following
|
||||
|
||||
```cpp
|
||||
class PrintingParser: public sfz::Parser
|
||||
{
|
||||
protected:
|
||||
void callback(absl::string_view header, const std::vector<sfz::Opcode>& members) final
|
||||
{
|
||||
switch (hash(header)) // The hash(...) function transforms strings to large integers
|
||||
{
|
||||
case hash("global"): // It is also compile-time defined, which allows to do switch-case
|
||||
// statements on strings, something that is usually not possible
|
||||
globalMembers = members; // We save the global headers since they apply to the next
|
||||
// region (and groups and masters)
|
||||
masterMembers.clear();
|
||||
groupMembers.clear();
|
||||
break;
|
||||
case hash("master"):
|
||||
masterMembers = members; // So on
|
||||
groupMembers.clear();
|
||||
break;
|
||||
case hash("group"):
|
||||
groupMembers = members; // .. and so forth
|
||||
break;
|
||||
case hash("region"):
|
||||
std::cout << "<" << header << ">" << ' '; // Now we print the region along with all the opcodes
|
||||
// we memorized from earlier headers.
|
||||
printMembers(globalMembers);
|
||||
printMembers(masterMembers);
|
||||
printMembers(groupMembers);
|
||||
printMembers(members);
|
||||
std::cout << '\n';
|
||||
break;
|
||||
default:
|
||||
std::cout << "<" << header << ">" << ' ';
|
||||
printMembers(members);
|
||||
std::cout << '\n';
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<sfz::Opcode> globalMembers;
|
||||
std::vector<sfz::Opcode> masterMembers;
|
||||
std::vector<sfz::Opcode> groupMembers;
|
||||
void printMembers(const std::vector<sfz::Opcode>& members)
|
||||
{
|
||||
for (auto& member: members)
|
||||
{
|
||||
std::cout << member.opcode;
|
||||
if (member.parameter)
|
||||
std::cout << +*member.parameter;
|
||||
std::cout << "=" << member.value;
|
||||
std::cout << ' ';
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The main function is then quite straightforward and we call a function from the Parser class that loads a file
|
||||
```cpp
|
||||
PrintingParser parser;
|
||||
parser.loadSfzFile("my_sfz_file.sfz");
|
||||
```
|
||||
If you circle back to the parser you will see that opcodes are stored in an `Opcode` class. This class does some parsing
|
||||
itself and separates the opcode name itself, parameters if any, and the value. Opcodes are very cheap to copy and pass
|
||||
around because they only refer to characters in the file that are stored inside the `Parser` class, so feel free to
|
||||
create vectors of them and move them around.
|
||||
|
||||
Note that you may also derive the loadSfzFile method if you have any processing you need to do before the actual parsing happens.
|
||||
|
||||
# Building the region list in sfizz
|
||||
|
||||
The callback method from sfizz is actually quite similar to the one shown above, except that instead of printing the region
|
||||
we actually fill a big structure from it.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# sfizz
|
||||
|
||||
SFZ file format library
|
||||
|
||||
- [public C API](sfizz_8h.html)
|
||||
- [public C++ API](classsfz_1_1_sfizz.html)
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Must be called from the root directory
|
||||
if [[ -f api_index.md ]]; then rm api_index.md; fi
|
||||
cat >>api_index.md <<EOF
|
||||
---
|
||||
title: "API"
|
||||
---
|
||||
EOF
|
||||
tags=()
|
||||
for tag in $(git tag --list); do
|
||||
if [[ ${tag} != "list" && ${tag} != *"test"* ]]; then
|
||||
tag=$(echo "${tag}" | sed -r 's/v//g')
|
||||
tags+=("${tag}")
|
||||
fi
|
||||
done
|
||||
IFS=$'\n' tags=($(sort <<<"${tags[*]}")); unset IFS
|
||||
for tag in "${tags[@]}"; do
|
||||
echo "- [${tag}](${tag})" >> api_index.md
|
||||
done
|
||||
185
scripts/doxygen/doxy2json.py
Normal file
185
scripts/doxygen/doxy2json.py
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
license. You should have receive a LICENSE.md file along with the code.
|
||||
If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
Converts the Doxygen XML output to a custom JSON structure.
|
||||
|
||||
The JSON output will be used on a Jekyll website,
|
||||
parsed by a related layout (_layouts/doxygen.html).
|
||||
|
||||
Known bugs / wish list:
|
||||
|
||||
- Replace `strip_tags_in_text()` and `tag_list_as_string()` with a recursive
|
||||
parsing function able to extract also detailed descriptions paragraphs
|
||||
(E.g. `sfizz_oversampling_factor_t` has 3), getting rid of various
|
||||
`@since`, `@note` and `@return`, which are parsed separately.
|
||||
It should also covert the Doxygen custom tags (like <bold>, see below,
|
||||
or should this be done by some XSLT trasformation file?).
|
||||
|
||||
- Tags in ALIASES list needs to be escaped (parsed by tag_list_as_string())
|
||||
to avoid Doxygen convert them in its own tag structure, by loosing some
|
||||
details (e.g.: <b style=\"color:blue\">true</b> becomes <bold>true</bold>).
|
||||
|
||||
- Merge the work done previously to be able to fully automate the process
|
||||
to be used in various CIs.
|
||||
"""
|
||||
import xml.etree.ElementTree as ET
|
||||
import json
|
||||
|
||||
# TODO: scan for files
|
||||
tree = ET.parse('xml/classsfz_1_1_sfizz.xml')
|
||||
root = tree.getroot()
|
||||
data = {}
|
||||
|
||||
def strip_tags_in_text(element):
|
||||
if element is None:
|
||||
return ""
|
||||
|
||||
returned_string = element.text or ""
|
||||
for t in element:
|
||||
if t.tag == "ref":
|
||||
returned_string += "<a href='#{}'>{}</a>".format(t.text.replace("()", ''), t.text)
|
||||
returned_string += t.tail or ""
|
||||
elif t.tag == "computeroutput":
|
||||
returned_string += "<code>{}</code>".format(t.text)
|
||||
returned_string += t.tail or ""
|
||||
else:
|
||||
returned_string += t.text or ""
|
||||
returned_string += t.tail or ""
|
||||
|
||||
return returned_string.strip()
|
||||
|
||||
def tag_list_as_string(element_list):
|
||||
if element_list is None or len(element_list) == 0:
|
||||
return ""
|
||||
|
||||
if element_list[0].text is not None:
|
||||
return element_list[0].text.strip()
|
||||
|
||||
returned_string = ""
|
||||
for element in element_list:
|
||||
for t in element:
|
||||
# if t.tag == "bold": t.tag = 'b'
|
||||
returned_string += ET.tostring(t, encoding="unicode")
|
||||
|
||||
return returned_string.strip()
|
||||
|
||||
name = root.find("./compounddef/compoundname")
|
||||
kind = root.find("./compounddef").get("kind")
|
||||
brief = root.find("./compounddef/briefdescription/para")
|
||||
include = root.find("./compounddef/includes")
|
||||
location = root.find("./compounddef/location").get("file")
|
||||
language = root.find("./compounddef").get("language")
|
||||
version = root.get("version")
|
||||
|
||||
if name is not None and name.text is not None: data["name"] = name.text
|
||||
if kind is not None: data["kind"] = kind
|
||||
if brief is not None and brief.text is not None: data["brief"] = brief.text.strip()
|
||||
if include is not None and include.text is not None: data["include"] = include.text.strip()
|
||||
if location is not None: data["location"] = location
|
||||
if language is not None: data["language"] = language
|
||||
if version is not None: data["doxygen_version"] = version
|
||||
definitions = []
|
||||
|
||||
for sectiondef in root.iter("sectiondef"):
|
||||
|
||||
def_kind = sectiondef.get("kind")
|
||||
definition = {}
|
||||
members = []
|
||||
definition["kind"] = def_kind
|
||||
|
||||
for memberdef in sectiondef:
|
||||
|
||||
member = {}
|
||||
member["name"] = memberdef.find("name").text
|
||||
|
||||
type_member = memberdef.find("type")
|
||||
initializer_member = memberdef.find("initializer")
|
||||
brief_member = memberdef.find("briefdescription/para")
|
||||
description_member = memberdef.find("detaileddescription/para")
|
||||
return_member = memberdef.findall("detaileddescription/para/simplesect[@kind='return']/para")
|
||||
since_member = memberdef.find("detaileddescription/para/simplesect[@kind='since']/para")
|
||||
note_member = memberdef.find("detaileddescription/para/simplesect[@kind='note']/para")
|
||||
|
||||
if type_member is not None:
|
||||
type_member = strip_tags_in_text(type_member)
|
||||
if type_member != '':
|
||||
member["type"] = type_member
|
||||
|
||||
if initializer_member is not None and initializer_member.text is not None:
|
||||
member["initializer"] = initializer_member.text
|
||||
|
||||
if brief_member is not None:
|
||||
member["brief"] = strip_tags_in_text(brief_member)
|
||||
|
||||
if description_member is not None:
|
||||
description_member = strip_tags_in_text(description_member)
|
||||
if description_member != '':
|
||||
member["description"] = description_member
|
||||
|
||||
if return_member is not None:
|
||||
return_member = tag_list_as_string(return_member)
|
||||
if return_member != '':
|
||||
member["return"] = return_member
|
||||
|
||||
if since_member is not None and since_member.text is not None:
|
||||
member["since"] = since_member.text.strip()
|
||||
|
||||
if note_member is not None and note_member.text is not None:
|
||||
member["note"] = strip_tags_in_text(note_member)
|
||||
|
||||
members.append(member)
|
||||
|
||||
if def_kind == "enum" or def_kind == "public-type":
|
||||
enumvalues = []
|
||||
for enumvalue in memberdef.iter("enumvalue"):
|
||||
enum = {}
|
||||
enum["name"] = enumvalue.find("name").text
|
||||
|
||||
initializer_member = enumvalue.find("initializer")
|
||||
brief_member = enumvalue.find("briefdescription/para")
|
||||
description_member = enumvalue.find("detaileddescription/para")
|
||||
|
||||
if initializer_member is not None and initializer_member.text is not None:
|
||||
enum["initializer"] = initializer_member.text
|
||||
|
||||
if brief_member is not None:
|
||||
enum["brief"] = strip_tags_in_text(brief_member)
|
||||
|
||||
if description_member is not None:
|
||||
enum["description"] = strip_tags_in_text(description_member)
|
||||
|
||||
enumvalues.append(enum)
|
||||
|
||||
member["values"] = enumvalues
|
||||
|
||||
params = []
|
||||
for paramtag in memberdef.findall("param"):
|
||||
|
||||
param = {}
|
||||
param["name"] = paramtag.find("declname").text
|
||||
param["type"] = strip_tags_in_text(paramtag.find("type"))
|
||||
|
||||
param_items = memberdef.findall("detaileddescription/para/parameterlist[@kind='param']/parameteritem")
|
||||
for param_item in param_items:
|
||||
param_name = param_item.find("parameternamelist/parametername").text
|
||||
if param_name == param.get("name"):
|
||||
description = param_item.find("parameterdescription/para")
|
||||
if description is not None:
|
||||
param["description"] = strip_tags_in_text(description)
|
||||
|
||||
params.append(param)
|
||||
|
||||
if params:
|
||||
member["params"] = params
|
||||
|
||||
definition["members"] = members
|
||||
definitions.append(definition)
|
||||
|
||||
data["definitions"] = definitions
|
||||
|
||||
print(json.dumps(data, indent=2))
|
||||
|
|
@ -245,7 +245,7 @@ if(WIN32)
|
|||
configure_file (${PROJECT_SOURCE_DIR}/scripts/innosetup.iss.in ${PROJECT_BINARY_DIR}/innosetup.iss @ONLY)
|
||||
endif()
|
||||
|
||||
configure_file (${PROJECT_SOURCE_DIR}/doxygen/scripts/Doxyfile.in ${PROJECT_SOURCE_DIR}/Doxyfile @ONLY)
|
||||
configure_file (${PROJECT_SOURCE_DIR}/scripts/doxygen/Doxyfile.in ${PROJECT_SOURCE_DIR}/Doxyfile @ONLY)
|
||||
|
||||
add_library (sfizz::parser ALIAS sfizz_parser)
|
||||
add_library (sfizz::sfizz ALIAS sfizz_static)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue