OpenTTD
fluidsynth.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD 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.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "../stdafx.h"
13 #include "../openttd.h"
14 #include "../sound_type.h"
15 #include "../debug.h"
16 #include "fluidsynth.h"
17 #include "midifile.hpp"
18 #include <fluidsynth.h>
19 #include "../mixer.h"
20 
21 static struct {
22  fluid_settings_t* settings;
23  fluid_synth_t* synth;
24  fluid_player_t* player;
25 } _midi;
26 
29 
31 static const char *default_sf[] = {
32  /* Debian/Ubuntu/OpenSUSE preferred */
33  "/usr/share/sounds/sf2/FluidR3_GM.sf2",
34 
35  /* RedHat/Fedora/Arch preferred */
36  "/usr/share/soundfonts/FluidR3_GM.sf2",
37 
38  /* Debian/Ubuntu/OpenSUSE alternatives */
39  "/usr/share/sounds/sf2/TimGM6mb.sf2",
40  "/usr/share/sounds/sf2/FluidR3_GS.sf2",
41 
42  NULL
43 };
44 
45 static void RenderMusicStream(int16 *buffer, size_t samples)
46 {
47  if (!_midi.synth || !_midi.player) return;
48  fluid_synth_write_s16(_midi.synth, samples, buffer, 0, 2, buffer, 1, 2);
49 }
50 
51 const char *MusicDriver_FluidSynth::Start(const char * const *param)
52 {
53  const char *sfont_name = GetDriverParam(param, "soundfont");
54  int sfont_id;
55 
56  DEBUG(driver, 1, "Fluidsynth: sf %s", sfont_name);
57 
58  /* Create the settings. */
59  _midi.settings = new_fluid_settings();
60  if (!_midi.settings) return "Could not create midi settings";
61 
62  /* Create the synthesizer. */
63  _midi.synth = new_fluid_synth(_midi.settings);
64  if (!_midi.synth) return "Could not open synth";
65 
66  /* Load a SoundFont and reset presets (so that new instruments
67  * get used from the SoundFont) */
68  if (!sfont_name) {
69  int i;
70  sfont_id = FLUID_FAILED;
71  for (i = 0; default_sf[i]; i++) {
72  if (!fluid_is_soundfont(default_sf[i])) continue;
73  sfont_id = fluid_synth_sfload(_midi.synth, default_sf[i], 1);
74  if (sfont_id != FLUID_FAILED) break;
75  }
76  if (sfont_id == FLUID_FAILED) return "Could not open any sound font";
77  } else {
78  sfont_id = fluid_synth_sfload(_midi.synth, sfont_name, 1);
79  if (sfont_id == FLUID_FAILED) return "Could not open sound font";
80  }
81 
82  _midi.player = NULL;
83 
84  uint32 samplerate = MxSetMusicSource(RenderMusicStream);
85  fluid_synth_set_sample_rate(_midi.synth, samplerate);
86  DEBUG(driver, 1, "Fluidsynth: samplerate %.0f", (float)samplerate);
87 
88  return NULL;
89 }
90 
92 {
93  MxSetMusicSource(NULL);
94  this->StopSong();
95  delete_fluid_synth(_midi.synth);
96  delete_fluid_settings(_midi.settings);
97 }
98 
100 {
101  std::string filename = MidiFile::GetSMFFile(song);
102 
103  this->StopSong();
104 
105  if (filename.empty()) {
106  return;
107  }
108 
109  _midi.player = new_fluid_player(_midi.synth);
110  if (!_midi.player) {
111  DEBUG(driver, 0, "Could not create midi player");
112  return;
113  }
114 
115  if (fluid_player_add(_midi.player, filename.c_str()) != FLUID_OK) {
116  DEBUG(driver, 0, "Could not open music file");
117  delete_fluid_player(_midi.player);
118  _midi.player = NULL;
119  return;
120  }
121  if (fluid_player_play(_midi.player) != FLUID_OK) {
122  DEBUG(driver, 0, "Could not start midi player");
123  delete_fluid_player(_midi.player);
124  _midi.player = NULL;
125  return;
126  }
127 }
128 
130 {
131  if (!_midi.player) return;
132 
133  fluid_player_stop(_midi.player);
134  if (fluid_player_join(_midi.player) != FLUID_OK) {
135  DEBUG(driver, 0, "Could not join player");
136  }
137  delete_fluid_player(_midi.player);
138  fluid_synth_system_reset(_midi.synth);
139  _midi.player = NULL;
140 }
141 
143 {
144  if (!_midi.player) return false;
145 
146  return fluid_player_get_status(_midi.player) == FLUID_PLAYER_PLAYING;
147 }
148 
150 {
151  /* Allowed range of synth.gain is 0.0 to 10.0 */
152  /* fluidsynth's default gain is 0.2, so use this as "full
153  * volume". Set gain using OpenTTD's volume, as a number between 0
154  * and 0.2. */
155  double gain = (1.0 * vol) / (128.0 * 5.0);
156  if (fluid_settings_setnum(_midi.settings, "synth.gain", gain) != 1) {
157  DEBUG(driver, 0, "Could not set volume");
158  }
159 }
const char * GetDriverParam(const char *const *parm, const char *name)
Get a string parameter the list of parameters.
Definition: driver.cpp:40
Metadata about a music track.
bool IsSongPlaying()
Are we currently playing a song?
Definition: fluidsynth.cpp:142
void StopSong()
Stop playing the current song.
Definition: fluidsynth.cpp:129
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:22
void Stop()
Stop this driver.
Definition: fluidsynth.cpp:91
Base for FluidSynth music playback.
uint32 MxSetMusicSource(MxStreamCallback music_callback)
Set source of PCM music.
Definition: mixer.cpp:230
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:36
fluid_synth_t * synth
FluidSynth synthesizer handle.
Definition: fluidsynth.cpp:23
static FMusicDriver_FluidSynth iFMusicDriver_FluidSynth
Factory for the FluidSynth driver.
Definition: fluidsynth.cpp:28
static std::string GetSMFFile(const MusicSongInfo &song)
Get the name of a Standard MIDI File for a given song.
Definition: midifile.cpp:1041
void PlaySong(const MusicSongInfo &song)
Play a particular song.
Definition: fluidsynth.cpp:99
static struct @24 _midi
Metadata about the midi we&#39;re playing.
void SetVolume(byte vol)
Set the volume, if possible.
Definition: fluidsynth.cpp:149
static const char * default_sf[]
List of sound fonts to try by default.
Definition: fluidsynth.cpp:31
Factory for the fluidsynth driver.
Definition: fluidsynth.h:35
const char * Start(const char *const *param)
Start this driver.
Definition: fluidsynth.cpp:51
fluid_player_t * player
FluidSynth MIDI player handle.
Definition: fluidsynth.cpp:24