Coder Social home page Coder Social logo

pyfluidsynth's Introduction

pyFluidSynth

Python bindings for FluidSynth

This package contains python bindings for FluidSynth. FluidSynth is a software synthesizer for generating music. It works like a MIDI synthesizer. You load patches, set parameters, then send NOTEON and NOTEOFF events to play notes. Instruments are defined in SoundFonts, generally files with the extension SF2. FluidSynth can either be used to play audio itself, or you can call a function that returns chunks of audio data and output the data to the soundcard yourself. FluidSynth works on all major platforms, so pyFluidSynth should also.

Requirements

FluidSynth (2.0.0 or later)

(optional) NumPy 1.0 or later for some features

NOTE: If you don't need all the features of FluidSynth you may be interested in tinysoundfont-pybind which is a self-contained Python package that includes TinySoundFont for SoundFont playback and is permissively licensed.

Installation

To use the latest official release:

pip install pyfluidsynth

Pre-release Versions

To use pre-release versions of this package, clone this repository, go to the repository directory, then do:

pip install .

Example

Here is a program that plays a chord for a second.

import time
import fluidsynth

fs = fluidsynth.Synth()
fs.start()

sfid = fs.sfload("example.sf2")
fs.program_select(0, sfid, 0, 0)

fs.noteon(0, 60, 30)
fs.noteon(0, 67, 30)
fs.noteon(0, 76, 30)

time.sleep(1.0)

fs.noteoff(0, 60)
fs.noteoff(0, 67)
fs.noteoff(0, 76)

time.sleep(1.0)

fs.delete()

First a Synth object is created to control playback. The start() method starts audio output in a separate thread.

To get sound, you need to choose an instrument. First load a SoundFont with sfload(), then select a bank and preset with program_select().

program_select(track, soundfontid, banknum, presetnum)

To start a note, use the noteon() method.

noteon(track, midinum, velocity)

To stop a note, use noteoff().

noteoff(track, midinum)

Managing Audio

You can also manage audio IO yourself and just use FluidSynth to calculate the samples for the music. You might do this, for example, in a game with WAV sound effects and algorithmically generated music. To do this, create the Synth object but don't call start(). To generate the next chunk of audio, call get_samples().

get_samples(len)

The length you pass will be the number of audio samples. Unless specified otherwise, FluidSynth assumes an output rate of 44100 Hz. The return value will be a Numpy array of samples. By default FluidSynth generates stereo sound, so the return array will be length 2 * len.

To join arrays together, use numpy.append().

To convert an array of samples into a string of bytes suitable for sending to the soundcard, use fluidsynth.raw_audio_string(samples).

Here is an example that generates a chord then plays the data using PyAudio.

import time
import numpy
import pyaudio
import fluidsynth

pa = pyaudio.PyAudio()
strm = pa.open(
    format = pyaudio.paInt16,
    channels = 2, 
    rate = 44100, 
    output = True)

s = []

fl = fluidsynth.Synth()

# Initial silence is 1 second
s = numpy.append(s, fl.get_samples(44100 * 1))

sfid = fl.sfload("example.sf2")
fl.program_select(0, sfid, 0, 0)

fl.noteon(0, 60, 30)
fl.noteon(0, 67, 30)
fl.noteon(0, 76, 30)

# Chord is held for 2 seconds
s = numpy.append(s, fl.get_samples(44100 * 2))

fl.noteoff(0, 60)
fl.noteoff(0, 67)
fl.noteoff(0, 76)

# Decay of chord is held for 1 second
s = numpy.append(s, fl.get_samples(44100 * 1))

fl.delete()

samps = fluidsynth.raw_audio_string(s)

print(len(samps))
print('Starting playback')
strm.write(samps)

Using the Sequencer

You can create a sequencer as follows:

import fluidsynth

seq = fluidsynth.Sequencer()

This will by default create a sequencer that will advance at a rate of 1000 ticks per second. To change the rate at which the sequencer advances, you can give it the optional time_scale parameter. As a clock source, it will use your system clock. In order to manually advance the sequencer, you can give it the parameter use_system_timer=False. You will then have to advance it using sequencer.process.

In order to make the sequencer aware of your synthesizer, you have to register it:

fs = fluidsynth.Synth()
# init and start the synthesizer as described above…

synthID = seq.register_fluidsynth(fs)

You have to keep the ID and use it as a target for the midi events you want to schedule. Now, you can sequence actual notes:

seq.note_on(time=500, absolute=False, channel=0, key=60, velocity=80, dest=synthID)

If you use relative timing like above, the sequencer will schedule the event the specified time from the current position. Otherwise, if absolute is True (the default), you have to use absolute track positions (in ticks). So the following code snippet will do the same as the one above:

current_time = seq.get_tick()
seq.note_on(current_time + 500, 0, 60, 80, dest=synthID)

You can also register your own callback functions to be called at certain ticks:

def seq_callback(time, event, seq, data):
    print('callback called!')

callbackID = sequencer.register_client("myCallback", seq_callback)

sequencer.timer(current_time + 2000, dest=callbackID)

Note that event and seq are low-level objects, not actual python objects.

You can find a complete example (inspired by this one from the fluidsynth library) in the test folder.

Bugs and Limitations

Not all functions in FluidSynth are bound.

Not much error checking, FluidSynth will segfault/crash if you call the functions incorrectly sometimes.

Authors

This project was originally created by Nathan Whitehead [email protected] but is the work of many. See CONTRIBUTORS.

License

Released under the LGPL v2.1 or any later version (this is the same as FluidSynth).

Copyright 2008--2024, Nathan Whitehead and contributors.

pyfluidsynth's People

Contributors

adarob avatar albedozero avatar avril112113 avatar cclauss avatar christianromberg avatar fruchtzwerg94 avatar kevinzakka avatar matael avatar matthewscholefield avatar nwhitehead avatar t-oster avatar therealadityashankar avatar uncompiled avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyfluidsynth's Issues

How to access reverb functionality

This library is in dire need of some kind of api docs - how do I set the reverb level?? I tried set_reverb but no matter what arguments i gave it, it wouldn't work

Delay on Raspberry Pi. Any way to set Chorus and Buffer Sizes?

Hi,

I am building a RaspberryPi based E-Drum with this. It is working and if I use pyfluidsynth on my Notebook, the latency is good, but if I use it one the PI, the latency is way to big (seems like a delay of 300-500ms).
here (https://raspberrypi.stackexchange.com/questions/14987/midi-keyboard-latency-with-fluidsynth) the suggestion is to fiddle with buffer sizes and turn of chorus etc. Is there any way to do this with pyfluisynth?

API docs

We need API docs.

For other recent projects I've used Sphinx and a github action to upload generated docs to github pages, I think that would be ok here.

Can't set "audio-bufsize"

Via fluidsynth command line you can set the audio buffer size via -z or --audio-bufsize. For some strage reason I need to set it on Fedora 36+ to get non-chopped output.
However there seems to be no way to set this value using Synth.settings. Despite those look somehow generic, there was no way to set it the setting() function
I tried: audio.bufsize, audio.buffer-size audio.buf-size, synth.bufsize, synth.buf-size, synth.audio-bufsize and some more without success.
Is there a way to workaround this?

I'm using pyFluidSynth v1.3.1 fluidsynth v2.3.1 on Python 3.10

AttributeError: module 'fluidsynth' has no attribute 'Synth'

80 def play_sequence(sequence,
81 synth=midi_synth.synthesize,
82 sample_rate=_DEFAULT_SAMPLE_RATE,
83 colab_ephemeral=True,
84 **synth_args):
85 """Creates an interactive player for a synthesized note sequence.
86
87 This function should only be called from a Jupyter or Colab notebook.
(...)
96 **synth_args: Additional keyword arguments to pass to the synth function.
97 """
---> 98 array_of_floats = synth(sequence, sample_rate=sample_rate, **synth_args)
...
--> 468 fl = fluidsynth.Synth(samplerate=fs)
469 # Load in the soundfont
470 sfid = fl.sfload(sf2_path)

AttributeError: module 'fluidsynth' has no attribute 'Synth'

Fix the driver selection

As discussed in #11, the way pyfluidsynth behaves with incorrect or unknown drivers is not really acceptable. It should at least be better documented.
In my opinion it would be quite nice to let pyfluidsynth automatically select the best available audio driver.

wrong type error

In attempting to use your script on FluidSynth 1.1.6, I get this error:

>>> fs = fluidsynth.Synth() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Program Files\Anaconda3\lib\site-packages\fluidsynth.py", line 192, in __init__ fluid_settings_setnum(st, 'synth.gain', gain) ctypes.ArgumentError: argument 2: <class 'TypeError'>: wrong type

I downloaded FluidSynth from here:
https://sourceforge.net/projects/jorgan/files/fluidsynth/Fluidsynth%201.1.6%2064-bit/

AttributeError: module 'fluidsynth' has no attribute 'Synth'

def display_audio(pm: pretty_midi.PrettyMIDI, seconds=30): waveform = pm.fluidsynth(fs=sampling_rate) waveform_short = waveform[:seconds*sampling_rate] return display.Audio(waveform_short, rate=sampling_rate)

This is the Code,
I installed fluidsynth by pip install --upgrade pyfluidsynth

dll name on windows

On my windows machine the dll name is "libfluidsynth64"

had to add this line at the top:

lib = find_library('libfluidsynth64')

I also removed the "set reverb full" and "set chorus full" functions, because they aren't present in that dll and gave me errors..

raise ImportError, "Couldn't find the FluidSynth library." on M1 Macbook

I use MacOS 12.3 (Monterey) on MacBook Pro (14-inch, 2021).

I installed fluidsynth by brew install fluidsynth, but my fluidsynth.py returned

  File "/Users/<myusername>/.pyenv/versions/<myPyenvName>/lib/python3.9/site-packages/fluidsynth.py", line 44, in <module>
    raise ImportError("Couldn't find the FluidSynth library.")
ImportError: Couldn't find the FluidSynth library.

When I ran import fluidsynth.

I tried adding /opt/homebrew/Cellar/fluid-synth/2.2.8_1/lib dir in my $PATH (the directory contains libfluidsynth.3.dylib), but the error message persisted.

Interestingly, when I import fluidsynth on my non-M1 macbook, the code worked as is.

Does anyone have an idea on what is wrong in my setting?

Reverb issue

When loading some .sf2 files, fluidsynth will not play a reverb - even when manually calling 'set_reverb()' with max roomsize, width, level.
Note that with certain .sf2 files, I'm getting an appropriate reverb response when changing the settings using set_reverb().

Looking for some assistance to fix this issue.

Version 1.2.5 is not on Pypi

Hey,

I just spend some hours trying to get pyfluidsynth running on OSX High Sierra only to find out that the PyPi version is 1.2.4.

Could you please update this to 1.2.5?

Thanks!

Error couldn't find FluidSynth library

I know a thread similar to this has been posted before, but I'm lost on what I need to do and solutions from that thread have failed me.

Currently, I have installed pyFluidSynth using the "py setup.py install --user" command on my command prompt and have set up Fluidsynth as a part of my PATH. I have tried including the .dll files directly as well as the fluidsynth folder that contains the bin folder.

All I'm trying to do is run a test file I found on the internet but I can't even get it to boot without having an error.
Capture

How to implement play_midi_file?

I've tried the below code but only get '0' as output and no sound. I feel like I'm missing something but couldn't figure it out from the documentation.

fs = fluidsynth.Synth()
fs.start()

sfid = fs.sfload(sound1)
fs.program_select(0, sfid, 0, 0)

fs.play_midi_file(midi_path)
fs.play_midi_stop()

The below code did work for me:

fs = fluidsynth.Synth()
fs.start()

sfid = fs.sfload(sound1)
fs.program_select(0, sfid, 0, 0)

fs.noteon(0, 60, 100)
fs.noteon(0, 67, 100)
fs.noteon(0, 76, 100)

time.sleep(1.0)

fs.noteoff(0, 60)
fs.noteoff(0, 67)
fs.noteoff(0, 76)

time.sleep(1.0)
fs.delete()

Please implement gain (trivial patch included)

Midi velocity doesn't just change volume of a rendered note. It also changes the attack. Having some way to change the volume without changing how the note sounds is important. As far as I can tell in my tinkering, this is as simple as exposing the functionality that fluidsynth already includes.

# If I understand what's going on correctly: 
...
fluid_synth_get_gain = cfunc('fluid_synth_get_gain', c_float,
                                    ('synth', c_void_p, 1))

fluid_synth_set_gain = cfunc('fluid_synth_set_gain', c_void_p,
                                    ('synth', c_void_p, 1),
                                    ('gain', c_float, 1))
...
class Synth:
...
    def get_gain(self) :
        return fluid_synth_get_gain(self.synth)
    def set_gain(self, gain) :
        return fluid_synth_set_gain(self.synth, float(gain))
...

ModuleNotFoundError: No module named 'FluidSynth'

I'm trying to install pyfluidsynth on windows. I used pip install pyfluidsynth in the command prompt, but when I tried to import fluidsynth in my python code I get:

ModuleNotFoundError: No module named 'FluidSynth'

When I tried to install FluidSynth (by using pip install fluidsynth) another binding package was install with FluidSynth 0.2 from several years ago.
Can anybody help with specific details how to install pyfluidsynth on windows and use it?
The error:
import FluidSynth
Traceback (most recent call last):
File "", line 1, in
File "C:\Program Files\JetBrains\PyCharm 2018.3.2\helpers\pydev_pydev_bundle\pydev_import_hook.py", line 21, in do_import
module = self._system_import(name, *args, **kwargs)
ModuleNotFoundError: No module named 'FluidSynth'

A working code for Jupiter Notebooks/Google Colabs and Windows Env.

Hey guys,

Since the fluidsynth and pyfluidsynth can't play output on Windows/Google Colabs, here is a little code that works just fine.
Reposting here from fluidsynth issues as recommended by fluidsynth contributors. I hope it is ok.

Its actually more of a hack/workaround but it does the job. Enjoy :)

!pip install pyFluidSynth
!apt install fluidsynth #Pip does not work for some reason. Only apt works
!pip install midi2audio

!cp /usr/share/sounds/sf2/FluidR3_GM.sf2 /content/font.sf2

from midi2audio import FluidSynth
from google.colab import output
from IPython.display import display, Javascript, HTML, Audio

FluidSynth("/content/font.sf2").midi_to_audio('output_midi.mid','output_wav.wav')
# set the src and play
Audio("output_wav.wav")

Error: No module named 'pyFluidSynth'

i have installed pyFluidSynth using pip but by import pyFluidSynth give an error :ModuleNotFoundError: No module named 'pyFluidSynth'.
also if i import fluidsynth the i get the error ImportError: Couldn't find the FluidSynth library.

pyfluidsynth import fails with fluidsynth 2.0.3

I get the following error every time any python script tries to import fluidsynth. Pyfluidsynth was installed via pip. I installed fluidsynth version 2.0.3 via homebrew as described here and also tried compiling it myself using cmake, which doesn't help. Simply calling fluidsynth from the command line works just fine. I'm on OSX 10.14.2 using Python 3.6.8. I was able to reproduce this error on one other machine using the same OS.

File "/anaconda3/envs/myenv/lib/python3.6/site-packages/fluidsynth.py", line 180, in <module>
    ('info', POINTER(fluid_synth_channel_info_t), 1))
  File "/anaconda3/envs/myenv/lib/python3.6/site-packages/fluidsynth.py", line 53, in cfunc
    return CFUNCTYPE(result, *atypes)((name, _fl), tuple(aflags))
AttributeError: dlsym(0x7fa26296ad10, fluid_synth_get_channel_info): symbol not found

Any help is highly appreciated, maybe I'm missing something obvious?

fs.program select and fs.note_on keep returning 0's with no sound

I'm using a custom SF2 file from the internet (clean electric guitar). However, when I use either fs.program_select(0, sfid, 0, 0) or fs.noteon(0, 60, 30) it prints a 0 to the Python terminal and does not play a sound.

Do you have the "example.sf2" file you call in the tutorial script? I want to make sure there's not something wrong with my drivers/set up. Thanks!

"NoneType object not callable” error when calling sfpreset_name()

Hello,
First of all, thanx very much for bringing PyFluidSynth.

I recently installed PyFluidSynth in a 32bit Windows environment, and managed to find a 32bit version of FluidSynth (wich is not so easy to find, unless I rebuild it) in a form of libfluidsynth-1.dll
I execute the first test listed on PyFluidSynth GitHub homepage and it works well.
Then I tried to call the following services and they fail with “NoneType object not callable” error :

  • fs.channel_info()
  • sfpreset_name(sfid, 0, 0)

Same issue with the example with the FluidSynth sequencer.

File "C:\Users\xxx\MyApp\Python3.7_32bits\lib\site-packages\fluidsynth.py", line 607, in channel_info
presetname = self.sfpreset_name(sfontid, banknum, prognum)
File "C:\Users\xxx\MyApp\Python3.7_32bits\lib\site-packages\fluidsynth.py", line 624, in sfpreset_name
preset=fluid_sfont_get_preset(sfont, bank, prog)
TypeError: 'NoneType' object is not callable

Did I miss something ?

Thanx in advance

Regards

ImportError: Couldn't find the FluidSynth library.

Hi guys,
I cloned the pyfluidsynth as a submodule into my repository. After that I followed the install instructions by running "python setup.py install". That was also completed successfully. I also downloaded fluidsynth-2.1.6-win10-x64.zip. However, when I run the code of test.test1.py I get the following error:

Traceback (most recent call last):
File "d:\Documents\05_programData\01_GitRepos\metronome\c_MIDIPlayback.py", line 2, in
from a_Libraries import fluidsynth
File "d:\Documents\05_programData\01_GitRepos\metronome\a_Libraries\fluidsynth.py", line 42, in
raise ImportError("Couldn't find the FluidSynth library.")
ImportError: Couldn't find the FluidSynth library.

I tried tracing it back following line 42 in fluidsynth.py. But since I'm pretty new to Python I lost track pretty quickly. Googling also didn't bring up anything useful.

I'd be super happy about help! And thanks for the (probably, couldn't really test it yet :D) cool library!

software details

  • Windows 10 64 bit
  • Python 3.7.9 64 bit
  • If you need more details tell me

pitch_bend doesn't work from Python

I have fluid-synth installed from homebrew and pyfluidsynth installed from pip (plus I had to edit the pyfluidsynth code so it could find the fluid-synth library).

I have verified that fluid-synth itself supports pitch bending by using its command line tool and giving it commands.

But the pitch_bend API doesn't seem to work in python. Here's a code sample that demonstrates the problem. I should hear two different notes, but this plays the same one twice.

import time
import fluidsynth

fs = fluidsynth.Synth(samplerate=44100.0)
fs.start() 

sfid = fs.sfload('FluidR3_GM.sf2')  # replace path as needed
fs.program_select(0, sfid, 0, 0)

time.sleep(1.0)

fs.pitch_bend(0, 8192)
fs.noteon(0, 60, 127)

time.sleep(1.0)
fs.noteoff(0, 60)

fs.pitch_bend(0, 10000)
fs.noteon(0, 60, 127)

time.sleep(3.0)

function 'fluid_synth_set_reverb_full' not found

Looks like pyfluidsynth uses internal functions:

  • fluid_synth_set_reverb_full
  • fluid_synth_set_chorus_full

They are only used in the internal sources of fluidsynth and are not exported.
They are also not present in the include directory for header files.
Tested on Windows. Note: as is, it might work on Linux/Mac, but not on Windows.

Suggested is to use the "public" API from include, which is properly exported in the DLL,

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);
FLUIDSYNTH_API int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping);
FLUIDSYNTH_API int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width);
FLUIDSYNTH_API int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level);

Full error output:

>python test1.py
Traceback (most recent call last):
  File "test1.py", line 2, in <module>
    import fluidsynth
  File "c:\Tools\Python27\lib\site-packages\fluidsynth.py", line 188, in <module>
    ('level', c_double, 1))
  File "c:\Tools\Python27\lib\site-packages\fluidsynth.py", line 53, in cfunc
    return CFUNCTYPE(result, *atypes)((name, _fl), tuple(aflags))
AttributeError: function 'fluid_synth_set_reverb_full' not found

Update PyPI version

The current version on PyPI (and therefore the default version installed by pip) is still 1.3.0, which has no support for FluidSynth 3.

@nwhitehead can upload the latest version to PyPI? Thanks!

Undefined names `chan` and `name` in the file `fluidsynth.py`

% ruff check --output-format=github --target-version=py38 .

Error: fluidsynth.py:772:75: F821 Undefined name `chan`
Error: fluidsynth.py:888:12: F821 Undefined name `fluid_synth_set_chorus_speed`
Error: fluidsynth.py:889:20: F821 Undefined name `fluid_synth_set_chorus_speed`
Error: fluidsynth.py:893:12: F821 Undefined name `fluid_synth_set_chorus_depth`
Error: fluidsynth.py:894:20: F821 Undefined name `fluid_synth_set_chorus_depth`
Error: fluidsynth.py:1002:64: F821 Undefined name `name`
Error: fluidsynth.py:1002:83: F821 Undefined name `name`
  • #51 highlights the problem with fluid_synth_set_chorus_speed.

chan and name are also not defined which will raise NameError if these lines of code are run.

% ruff rule F821

undefined-name (F821)

Derived from the Pyflakes linter.

What it does

Checks for uses of undefined names.

Why is this bad?

An undefined name is likely to raise NameError at runtime.

Example

def double():
    return n * 2  # raises `NameError` if `n` is undefined when `double` is called

Use instead:

def double(n):
    return n * 2

References

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.