-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4323b43
Showing
22 changed files
with
907 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Package: fluidsynth | ||
Type: Package | ||
Title: Read and Play Digital Music (MIDI) | ||
Version: 1.0.0 | ||
Authors@R: c( | ||
person("Jeroen", "Ooms", role = c("aut", "cre"), email = "jeroen@berkeley.edu", | ||
comment = c(ORCID = "0000-0002-4035-0289")), | ||
person("S. Christian Collins", role = "cph", comment = "author of generaluser-gs | ||
soundbank")) | ||
Description: Bindings to 'libfluidsynth' to parse and synthesize MIDI files. It can | ||
read MIDI into a data frame, play it on the local audio device, or convert into | ||
an audio file. | ||
License: MIT + file LICENSE | ||
Encoding: UTF-8 | ||
RoxygenNote: 7.3.1 | ||
Imports: av, rappdirs | ||
SystemRequirements: fluidsynth: fluidsynth-devel (rpm) or | ||
libfluidsynth-dev (deb). On Linux you also need a soundfont | ||
provided by 'fluid-soundfont-gm' (Fedora) or 'sf3-soundfont-gm' | ||
(Debian/Ubuntu) | ||
URL: https://docs.ropensci.org/fluidsynth/ | ||
https://ropensci.r-universe.dev/fluidsynth | ||
BugReports: https://github.com/ropensci/fluidsynth/issues | ||
NeedsCompilation: yes | ||
Packaged: 2024-02-19 23:14:30 UTC; jeroen | ||
Author: Jeroen Ooms [aut, cre] (<https://orcid.org/0000-0002-4035-0289>), | ||
S. Christian Collins [cph] (author of generaluser-gs soundbank) | ||
Maintainer: Jeroen Ooms <jeroen@berkeley.edu> | ||
Repository: CRAN | ||
Date/Publication: 2024-02-21 15:40:02 UTC |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
YEAR: 2024 | ||
COPYRIGHT HOLDER: Jeroen Ooms |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
4f13dcd6b0771828048e22f50a5f08f3 *DESCRIPTION | ||
66b8d6ae536d10339b4a28d0c792c08c *LICENSE | ||
62b15399b04abb67f3f82b8371ac79a8 *NAMESPACE | ||
0a88f8da8f2f45dade47f867a98da506 *R/init.R | ||
4218fb4c765df88a99385a871148a3d9 *R/midi.R | ||
5c75da8b3f770f79d8cf713ada3a3c43 *R/settings.R | ||
0dfd0e59c5e90f29a7b9e671d270de8e *R/soundfonts.R | ||
332211638884147974048affa6ca853e *configure | ||
7c46d904a1cf40891dd1f1888727ec30 *inst/midi/All_Night_Long.mid | ||
29d3b2e51d8d5c89b57ca1553d44050b *inst/midi/README.txt | ||
c9fbecdaf525751144852fa285681db8 *man/fluidsynth.Rd | ||
0336e0682a115aae65d1cffcd95addd2 *man/fluidsynth_settings.Rd | ||
f38b15ade099ab1ecb8705c4ecb6e68e *man/soundfonts.Rd | ||
c34834960e96714a1edfa0a9b4eb9551 *src/Makevars.in | ||
2077d6fdae6bede2de6ee21c6f5bc79e *src/Makevars.ucrt | ||
34b7f6afc470087befc51974f2a0d85c *src/Makevars.win | ||
004408fb0b8d1e04d3e18a280e013a7f *src/init.c | ||
641e310d83fd1b3b6c2ff4e7266ec3ff *src/playmidi.c | ||
bf39bafc7efb1aaf140b91f86899691a *src/readmidi.c | ||
cf9567ef3d8ab4f30d5667a2ea900376 *src/settings.c | ||
a8b9dcfcc803af566c89d1e01ffa4bc6 *tools/winlibs.R |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generated by roxygen2: do not edit by hand | ||
|
||
export(demo_midi) | ||
export(fluidsynth_setting_default) | ||
export(fluidsynth_setting_list) | ||
export(fluidsynth_setting_options) | ||
export(libfluidsynth_version) | ||
export(midi_convert) | ||
export(midi_play) | ||
export(midi_read) | ||
export(soundfont_download) | ||
export(soundfont_path) | ||
useDynLib(fluidsynth,C_fluidsynth_get_default) | ||
useDynLib(fluidsynth,C_fluidsynth_list_options) | ||
useDynLib(fluidsynth,C_fluidsynth_list_settings) | ||
useDynLib(fluidsynth,C_fluidsynth_version) | ||
useDynLib(fluidsynth,C_midi_play) | ||
useDynLib(fluidsynth,C_midi_read) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.onAttach <- function(libname, pkg){ | ||
packageStartupMessage(paste("Using libfluidsynth", libfluidsynth_version())) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#' Play or convert a midi file | ||
#' | ||
#' Play a midi file to your audio device, render it to a file, or parse the raw data. | ||
#' Additional settings can be specified, see [fluidsynth_setting_list] for available | ||
#' options. | ||
#' | ||
#' The `midi_convert` function internally uses fluidsynth to generate a raw wav file, | ||
#' and then [av::av_audio_convert()] to convert into the requested about format. See | ||
#' [av::av_muxers()] for supported output formats and their corresponding file extension. | ||
#' | ||
#' You need a soundfont to synthesize midi, see the [soundfonts] page. On Linux you may | ||
#' also need to specify an `audio.driver` that works for your hardware, although on | ||
#' recent distributions the defaults generally work. | ||
#' | ||
#' @useDynLib fluidsynth C_midi_play | ||
#' @export | ||
#' @rdname fluidsynth | ||
#' @family fluidsynth | ||
#' @returns midi_read returns data frame with midi events. | ||
#' @param midi path to the midi file | ||
#' @param soundfont path to the soundfont | ||
#' @param settings a named vector with additional settings from [fluidsynth_setting_list()] | ||
#' @param audio.driver which audio driver to use, | ||
#' see [fluidsynth docs](https://www.fluidsynth.org/api/CreatingAudioDriver.html) | ||
#' @examples | ||
#' df <- midi_read(demo_midi()) | ||
midi_play <- function(midi = demo_midi(), soundfont = soundfont_path(), audio.driver = NULL, | ||
settings = list(), verbose = interactive()){ | ||
midi <- normalizePath(midi, mustWork = TRUE) | ||
soundfont <- normalizePath(soundfont, mustWork = TRUE) | ||
verbose <- as.logical(verbose) | ||
audio.driver <- as.character(audio.driver) | ||
settings <- validate_fluidsynth_settings(settings) | ||
.Call(C_midi_play, midi, soundfont, audio.driver, settings, verbose) | ||
invisible() | ||
} | ||
|
||
#' @rdname fluidsynth | ||
#' @export | ||
#' @param output filename of the output. The out | ||
#' @param verbose print some progress status to the terminal | ||
midi_convert <- function(midi = demo_midi(), soundfont = soundfont_path(), output = 'output.mp3', | ||
settings = list(), verbose = interactive()){ | ||
midi <- normalizePath(midi, mustWork = TRUE) | ||
soundfont <- normalizePath(soundfont, mustWork = TRUE) | ||
tmp <- structure(tempfile(fileext = '.wav'), class = 'outputfile') | ||
on.exit(unlink(tmp)) | ||
verbose <- as.logical(verbose) | ||
settings <- validate_fluidsynth_settings(settings) | ||
.Call(C_midi_play, midi, soundfont, tmp, settings, verbose) | ||
av::av_audio_convert(tmp, output, verbose = verbose) | ||
} | ||
|
||
#' @export | ||
#' @rdname fluidsynth | ||
#' @useDynLib fluidsynth C_midi_read | ||
midi_read <- function(midi = demo_midi(), verbose = FALSE){ | ||
midi <- normalizePath(midi, mustWork = TRUE) | ||
verbose <- as.logical(verbose) | ||
out <- .Call(C_midi_read, midi, verbose) | ||
names(out) <- c("tick", "channel", "event", "param1", "param2") | ||
out$event <- factor(out$event, levels = c(midi_events), labels = names(midi_events)) | ||
data.frame(out) | ||
} | ||
|
||
#' @export | ||
#' @rdname fluidsynth | ||
demo_midi <- function(){ | ||
list.files(system.file(package = 'fluidsynth', 'midi'), pattern = '\\.mid$', full.names = TRUE) | ||
} | ||
|
||
# Values from: https://github.com/FluidSynth/fluidsynth/blob/master/src/midi/fluid_midi.h#L46C1-L71C27 | ||
midi_events <- c( | ||
NOTE_OFF = 0x80, | ||
NOTE_ON = 0x90, | ||
KEY_PRESSURE = 0xa0, | ||
CONTROL_CHANGE = 0xb0, | ||
PROGRAM_CHANGE = 0xc0, | ||
CHANNEL_PRESSURE = 0xd0, | ||
PITCH_BEND = 0xe0, | ||
MIDI_SYSEX = 0xf0, | ||
MIDI_TIME_CODE = 0xf1, | ||
MIDI_SONG_POSITION = 0xf2, | ||
MIDI_SONG_SELECT = 0xf3, | ||
MIDI_TUNE_REQUEST = 0xf6, | ||
MIDI_EOX = 0xf7, | ||
MIDI_SYNC = 0xf8, | ||
MIDI_TICK = 0xf9, | ||
MIDI_START = 0xfa, | ||
MIDI_CONTINUE = 0xfb, | ||
MIDI_STOP = 0xfc, | ||
MIDI_ACTIVE_SENSING = 0xfe, | ||
MIDI_SYSTEM_RESET = 0xff, | ||
MIDI_META_EVENT = 0xff | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#' Fluidsynth settings | ||
#' | ||
#' Get available settings and their types. | ||
#' See [fluidsynth docs](https://www.fluidsynth.org/api/fluidsettings.html) | ||
#' for more information on the available options. | ||
#' | ||
#' @export | ||
#' @name fluidsynth_settings | ||
#' @rdname fluidsynth_settings | ||
#' @family fluidsynth | ||
#' @returns a list with available options | ||
#' @useDynLib fluidsynth C_fluidsynth_list_settings | ||
#' @references [FluidSynth Settings Reference](https://www.fluidsynth.org/api/fluidsettings.html) | ||
#' @examples | ||
#' # List available settings: | ||
#' fluidsynth_setting_list() | ||
#' fluidsynth_setting_options('audio.driver') | ||
#' fluidsynth_setting_default('synth.sample-rate') | ||
fluidsynth_setting_list <- function(){ | ||
out <- .Call(C_fluidsynth_list_settings) | ||
names(out) <- c('name', 'type') | ||
data.frame(out) | ||
} | ||
|
||
#' @export | ||
#' @rdname fluidsynth_settings | ||
#' @useDynLib fluidsynth C_fluidsynth_list_options | ||
#' @param setting string with one of the options listed in [fluidsynth_setting_list()], see examples. | ||
fluidsynth_setting_options <- function(setting){ | ||
setting <- as.character(setting) | ||
.Call(C_fluidsynth_list_options, setting) | ||
} | ||
|
||
#' @export | ||
#' @rdname fluidsynth_settings | ||
#' @useDynLib fluidsynth C_fluidsynth_get_default | ||
fluidsynth_setting_default <- function(setting){ | ||
setting <- as.character(setting) | ||
.Call(C_fluidsynth_get_default, setting) | ||
} | ||
|
||
#' @export | ||
#' @rdname fluidsynth_settings | ||
#' @useDynLib fluidsynth C_fluidsynth_version | ||
libfluidsynth_version <- function(){ | ||
.Call(C_fluidsynth_version) | ||
} | ||
|
||
validate_fluidsynth_settings <- function(opts){ | ||
if(length(opts)){ | ||
settings <- fluidsynth_setting_list() | ||
for(o in names(opts)){ | ||
if(!(o %in% settings$name)) | ||
stop("Unsupported fluidsynth option: ", o) | ||
val <- opts[[o]] | ||
if(length(val) != 1) | ||
stop("Option is not of length 1: ", o) | ||
type <- settings[settings$name == o, "type"] | ||
if(type == 'string' && !is.character(val)) | ||
stop("Option should be a string: ", o) | ||
if(type != 'string'){ | ||
if(!is.numeric(val)) | ||
stop("Option should be a number: ", o) | ||
opts[[o]] <- as.numeric(val) | ||
} | ||
} | ||
return(opts) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#' Managing soundfonts | ||
#' | ||
#' FluidSynth requires a soundfont to synthesize a midi. On Linux distributions | ||
#' some soundfonts are often preinstalled, though their quality varies. If your | ||
#' midi sounds very poor, try using another soundfont. | ||
#' | ||
#' [GeneralUser-GS](https://schristiancollins.com/generaluser) by S. Christian Collins | ||
#' is a nice free soundfont. You can use `soundfont_download()` to install a copy | ||
#' of this soundbank for use by this package. | ||
#' | ||
#' @export | ||
#' @name soundfonts | ||
#' @rdname soundfonts | ||
#' @family fluidsynth | ||
#' @returns the path to a local soundfont to synthesize a midi file. | ||
#' @param download automatically download soundfont if none exists. | ||
soundfont_path <- function(download = FALSE){ | ||
if(file.exists(generaluser_gs_path())){ | ||
return(generaluser_gs_path()) | ||
} | ||
default <- fluidsynth_setting_default('synth.default-soundfont') | ||
if(file.exists(default)){ | ||
return(default) | ||
} | ||
if(grepl('redhat-linux', R.version$platform)){ | ||
stop('No soundfont found. Install one using either "yum install fluid-soundfont-gm" or in R: soundfont_download()') | ||
} | ||
if(isTRUE(download)){ | ||
return(soundfont_download()) | ||
} | ||
stop('No default soundfont found. You can install using: soundfont_download()') | ||
} | ||
|
||
#' @export | ||
#' @rdname soundfonts | ||
soundfont_download <- function(){ | ||
path <- generaluser_gs_path() | ||
if(!file.exists(path)){ | ||
url <- 'https://github.com/ropensci/fluidsynth/releases/download/generaluser-gs-v1.471/generaluser-gs-v1.471.zip' | ||
if(getOption('timeout') < 300) { | ||
old <- options(timeout = 300) | ||
on.exit(options(old)) | ||
} | ||
tmp <- tempfile(fileext = '.zip') | ||
on.exit(unlink(tmp), add = TRUE) | ||
utils::download.file(url, tmp, quiet = TRUE) | ||
dir.create(dirname(path), showWarnings = FALSE) | ||
utils::unzip(tmp, exdir = dirname(path)) | ||
} | ||
return(path) | ||
} | ||
|
||
generaluser_gs_path <- function(){ | ||
file.path(rappdirs::user_data_dir('soundfonts'), 'generaluser-gs/v1.471.sf2') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Anticonf (tm) script by Jeroen Ooms (2024) | ||
# This script will query 'pkg-config' for the required cflags and ldflags. | ||
# If pkg-config is unavailable or does not find the library, try setting | ||
# INCLUDE_DIR and LIB_DIR manually via e.g: | ||
# R CMD INSTALL --configure-vars='INCLUDE_DIR=/.../include LIB_DIR=/.../lib' | ||
|
||
# Library settings | ||
PKG_CONFIG_NAME="fluidsynth" | ||
PKG_DEB_NAME="libfluidsynth-dev" | ||
PKG_RPM_NAME="fluidsynth-devel" | ||
PKG_BREW_NAME="fluidsynth" | ||
PKG_TEST_HEADER="<fluidsynth.h>" | ||
PKG_LIBS="-lfluidsynth" | ||
|
||
# Use pkg-config if available | ||
if [ `command -v pkg-config` ]; then | ||
PKGCONFIG_CFLAGS=`pkg-config --cflags --silence-errors ${PKG_CONFIG_NAME}` | ||
PKGCONFIG_LIBS=`pkg-config --libs ${PKG_CONFIG_NAME}` | ||
fi | ||
|
||
# Note that cflags may be empty in case of success | ||
if [ "$INCLUDE_DIR" ] || [ "$LIB_DIR" ]; then | ||
echo "Found INCLUDE_DIR and/or LIB_DIR!" | ||
PKG_CFLAGS="-I$INCLUDE_DIR $PKG_CFLAGS" | ||
PKG_LIBS="-L$LIB_DIR $PKG_LIBS" | ||
elif [ "$PKGCONFIG_CFLAGS" ] || [ "$PKGCONFIG_LIBS" ]; then | ||
echo "Found pkg-config cflags and libs!" | ||
PKG_CFLAGS=${PKGCONFIG_CFLAGS} | ||
PKG_LIBS=${PKGCONFIG_LIBS} | ||
elif [ `uname` = "Darwin" ]; then | ||
test ! "$CI" && brew --version 2>/dev/null | ||
if [ $? -eq 0 ]; then | ||
BREWDIR=`brew --prefix` | ||
PKG_CFLAGS="-I$BREWDIR/include" | ||
PKG_LIBS="-L$BREWDIR/lib $PKG_LIBS" | ||
else | ||
curl -sfL "https://autobrew.github.io/scripts/fluid-synth" > autobrew | ||
. ./autobrew | ||
fi | ||
fi | ||
|
||
|
||
# For debugging | ||
echo "Using PKG_CFLAGS=$PKG_CFLAGS" | ||
echo "Using PKG_LIBS=$PKG_LIBS" | ||
|
||
# Find compiler | ||
CC=`${R_HOME}/bin/R CMD config CC` | ||
CFLAGS=`${R_HOME}/bin/R CMD config CFLAGS` | ||
CPPFLAGS=`${R_HOME}/bin/R CMD config CPPFLAGS` | ||
|
||
# Test configuration | ||
echo "#include $PKG_TEST_HEADER" | ${CC} ${CPPFLAGS} ${PKG_CFLAGS} ${CFLAGS} -E -xc - >/dev/null 2>configure.log | ||
|
||
# Customize the error | ||
if [ $? -ne 0 ]; then | ||
echo "--------------------------- [ANTICONF] --------------------------------" | ||
echo "Configuration failed because $PKG_CONFIG_NAME was not found. Try installing:" | ||
echo " * deb: $PKG_DEB_NAME (Debian, Ubuntu, etc)" | ||
echo " * rpm: $PKG_RPM_NAME (Fedora, EPEL)" | ||
echo " * brew: $PKG_BREW_NAME (OSX)" | ||
echo "If $PKG_CONFIG_NAME is already installed, check that 'pkg-config' is in your" | ||
echo "PATH and PKG_CONFIG_PATH contains a $PKG_CONFIG_NAME.pc file. If pkg-config" | ||
echo "is unavailable you can set INCLUDE_DIR and LIB_DIR manually via:" | ||
echo "R CMD INSTALL --configure-vars='INCLUDE_DIR=... LIB_DIR=...'" | ||
echo "-------------------------- [ERROR MESSAGE] ---------------------------" | ||
cat configure.log | ||
echo "--------------------------------------------------------------------" | ||
exit 1 | ||
fi | ||
|
||
# On Linux we need to initiate SDL manually | ||
case "$PKG_CFLAGS" in | ||
*SDL2*) | ||
PKG_CFLAGS="$PKG_CFLAGS -DHAS_LIBSDL2" | ||
PKG_LIBS="$PKG_LIBS -lSDL2" | ||
;; | ||
esac | ||
|
||
# Write to Makevars | ||
sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" src/Makevars.in > src/Makevars | ||
|
||
# Success | ||
exit 0 |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
This demo file is included with the free GeneralUser-GS soundbank. | ||
See https://www.schristiancollins.com/generaluser | ||
|
Oops, something went wrong.