an untested work in progress of BSoftSynth using fluidsynth (it's a try out and could be reverted if we feel like it)
libfluidsynth.so isn't on the image yet git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17844 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
SubDir HAIKU_TOP src kits midi ;
|
||||
|
||||
UsePrivateHeaders midi ;
|
||||
UseLibraryHeaders fluidsynth ;
|
||||
|
||||
SharedLibrary libmidi.so :
|
||||
Midi.cpp
|
||||
@@ -16,4 +17,6 @@ SharedLibrary libmidi.so :
|
||||
:
|
||||
be
|
||||
midi2
|
||||
media
|
||||
libfluidsynth.so
|
||||
;
|
||||
|
||||
+197
-217
@@ -23,7 +23,6 @@
|
||||
|
||||
#include <MidiRoster.h>
|
||||
#include <MidiConsumer.h>
|
||||
#include <MidiProducer.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Path.h>
|
||||
#include <string.h>
|
||||
@@ -35,25 +34,25 @@
|
||||
|
||||
using namespace BPrivate;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
BSoftSynth::BSoftSynth()
|
||||
: fSynth(NULL),
|
||||
fSettings(NULL),
|
||||
fSoundPlayer(NULL)
|
||||
{
|
||||
instrumentsFile = NULL;
|
||||
fInstrumentsFile = NULL;
|
||||
SetDefaultInstrumentsFile();
|
||||
|
||||
sampleRate = 22050;
|
||||
interpMode = B_LINEAR_INTERPOLATION;
|
||||
maxVoices = 28;
|
||||
limiterThreshold = 7;
|
||||
reverbEnabled = true;
|
||||
reverbMode = B_REVERB_BALLROOM;
|
||||
volumeScale = 1.0;
|
||||
fSampleRate = 44100;
|
||||
fInterpMode = B_LINEAR_INTERPOLATION;
|
||||
fMaxVoices = 256;
|
||||
fLimiterThreshold = 7;
|
||||
fReverbEnabled = true;
|
||||
fReverbMode = B_REVERB_BALLROOM;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
BSoftSynth::~BSoftSynth()
|
||||
{
|
||||
@@ -67,37 +66,36 @@ BSoftSynth::~BSoftSynth()
|
||||
Done();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool BSoftSynth::InitCheck(void) const
|
||||
bool
|
||||
BSoftSynth::InitCheck(void) const
|
||||
{
|
||||
return initCheck;
|
||||
return fInitCheck;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::Unload(void)
|
||||
void
|
||||
BSoftSynth::Unload(void)
|
||||
{
|
||||
/* TODO: purge samples from memory */
|
||||
|
||||
free(instrumentsFile);
|
||||
instrumentsFile = NULL;
|
||||
free(fInstrumentsFile);
|
||||
fInstrumentsFile = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool BSoftSynth::IsLoaded(void) const
|
||||
bool
|
||||
BSoftSynth::IsLoaded(void) const
|
||||
{
|
||||
return instrumentsFile != NULL;
|
||||
return fInstrumentsFile != NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::SetDefaultInstrumentsFile()
|
||||
status_t
|
||||
BSoftSynth::SetDefaultInstrumentsFile()
|
||||
{
|
||||
BPath path;
|
||||
if (B_OK == find_directory(B_SYNTH_DIRECTORY, &path, false, NULL))
|
||||
{
|
||||
if (B_OK == find_directory(B_SYNTH_DIRECTORY, &path, false, NULL)) {
|
||||
path.Append(B_BIG_SYNTH_FILE);
|
||||
return SetInstrumentsFile(path.Path());
|
||||
}
|
||||
@@ -105,9 +103,9 @@ status_t BSoftSynth::SetDefaultInstrumentsFile()
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::SetInstrumentsFile(const char* path)
|
||||
status_t
|
||||
BSoftSynth::SetInstrumentsFile(const char* path)
|
||||
{
|
||||
if (path == NULL)
|
||||
return B_BAD_VALUE;
|
||||
@@ -115,13 +113,13 @@ status_t BSoftSynth::SetInstrumentsFile(const char* path)
|
||||
if (IsLoaded())
|
||||
Unload();
|
||||
|
||||
instrumentsFile = strdup(path);
|
||||
fInstrumentsFile = strdup(path);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::LoadAllInstruments()
|
||||
status_t
|
||||
BSoftSynth::LoadAllInstruments()
|
||||
{
|
||||
/* TODO: Should load all of the instruments from the sample bank. */
|
||||
|
||||
@@ -129,387 +127,369 @@ status_t BSoftSynth::LoadAllInstruments()
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::LoadInstrument(int16 instrument)
|
||||
status_t
|
||||
BSoftSynth::LoadInstrument(int16 instrument)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::UnloadInstrument(int16 instrument)
|
||||
status_t
|
||||
BSoftSynth::UnloadInstrument(int16 instrument)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::RemapInstrument(int16 from, int16 to)
|
||||
status_t
|
||||
BSoftSynth::RemapInstrument(int16 from, int16 to)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::FlushInstrumentCache(bool startStopCache)
|
||||
void
|
||||
BSoftSynth::FlushInstrumentCache(bool startStopCache)
|
||||
{
|
||||
// TODO: we may decide not to support this function because it's weird!
|
||||
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::SetVolume(double volume)
|
||||
void
|
||||
BSoftSynth::SetVolume(double volume)
|
||||
{
|
||||
if (volume >= 0.0)
|
||||
{
|
||||
volumeScale = volume;
|
||||
if (volume >= 0.0) {
|
||||
fluid_synth_set_gain(fSynth, volume);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
double BSoftSynth::Volume(void) const
|
||||
double
|
||||
BSoftSynth::Volume(void) const
|
||||
{
|
||||
return volumeScale;
|
||||
return fluid_synth_get_gain(fSynth);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::SetSamplingRate(int32 rate)
|
||||
status_t
|
||||
BSoftSynth::SetSamplingRate(int32 rate)
|
||||
{
|
||||
// TODO: According to the BeBook, we should round rate to the nearest
|
||||
// acceptable value. However, this function may change depending on the
|
||||
// softsynth back-end we'll use.
|
||||
|
||||
if (rate == 11025 || rate == 22050 || rate == 44100)
|
||||
{
|
||||
sampleRate = rate;
|
||||
if (rate == 22050 || rate == 44100 || rate == 48000) {
|
||||
fSampleRate = rate;
|
||||
Init();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int32 BSoftSynth::SamplingRate() const
|
||||
int32
|
||||
BSoftSynth::SamplingRate() const
|
||||
{
|
||||
return sampleRate;
|
||||
return fSampleRate;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::SetInterpolation(interpolation_mode mode)
|
||||
status_t
|
||||
BSoftSynth::SetInterpolation(interpolation_mode mode)
|
||||
{
|
||||
// TODO: this function could change depending on the synth back-end.
|
||||
|
||||
interpMode = mode;
|
||||
// not used because our synth uses the same format than the soundplayer
|
||||
fInterpMode = mode;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
interpolation_mode BSoftSynth::Interpolation() const
|
||||
interpolation_mode
|
||||
BSoftSynth::Interpolation() const
|
||||
{
|
||||
return interpMode;
|
||||
return fInterpMode;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::EnableReverb(bool enabled)
|
||||
status_t
|
||||
BSoftSynth::EnableReverb(bool enabled)
|
||||
{
|
||||
reverbEnabled = enabled;
|
||||
fReverbEnabled = enabled;
|
||||
fluid_synth_set_reverb_on(fSynth, enabled);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool BSoftSynth::IsReverbEnabled() const
|
||||
bool
|
||||
BSoftSynth::IsReverbEnabled() const
|
||||
{
|
||||
return reverbEnabled;
|
||||
return fReverbEnabled;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::SetReverb(reverb_mode mode)
|
||||
void
|
||||
BSoftSynth::SetReverb(reverb_mode mode)
|
||||
{
|
||||
// TODO: this function could change depending on the synth back-end.
|
||||
|
||||
reverbMode = mode;
|
||||
fReverbMode = mode;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
reverb_mode BSoftSynth::Reverb() const
|
||||
reverb_mode
|
||||
BSoftSynth::Reverb() const
|
||||
{
|
||||
return reverbMode;
|
||||
return fReverbMode;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::SetMaxVoices(int32 max)
|
||||
status_t
|
||||
BSoftSynth::SetMaxVoices(int32 max)
|
||||
{
|
||||
// TODO: this function could change depending on the synth back-end.
|
||||
|
||||
if (max > 0 && max <= 32)
|
||||
{
|
||||
maxVoices = max;
|
||||
if (max > 0 && max <= 4096) {
|
||||
fMaxVoices = max;
|
||||
Init();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int16 BSoftSynth::MaxVoices(void) const
|
||||
int16
|
||||
BSoftSynth::MaxVoices(void) const
|
||||
{
|
||||
return maxVoices;
|
||||
return fMaxVoices;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
status_t BSoftSynth::SetLimiterThreshold(int32 threshold)
|
||||
status_t
|
||||
BSoftSynth::SetLimiterThreshold(int32 threshold)
|
||||
{
|
||||
// TODO: this function could change depending on the synth back-end.
|
||||
|
||||
if (threshold > 0 && threshold <= 32)
|
||||
{
|
||||
limiterThreshold = threshold;
|
||||
// not used
|
||||
if (threshold > 0 && threshold <= 32) {
|
||||
fLimiterThreshold = threshold;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int16 BSoftSynth::LimiterThreshold(void) const
|
||||
int16
|
||||
BSoftSynth::LimiterThreshold(void) const
|
||||
{
|
||||
return limiterThreshold;
|
||||
return fLimiterThreshold;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::Pause(void)
|
||||
void
|
||||
BSoftSynth::Pause(void)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::Resume(void)
|
||||
void
|
||||
BSoftSynth::Resume(void)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::NoteOff(
|
||||
void
|
||||
BSoftSynth::NoteOff(
|
||||
uchar channel, uchar note, uchar velocity, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SprayNoteOff(
|
||||
channel - 1, note, velocity, MAKE_BIGTIME(time));
|
||||
fluid_synth_noteoff(fSynth, channel - 1, note); // velocity isn't used in FS
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::NoteOn(
|
||||
void
|
||||
BSoftSynth::NoteOn(
|
||||
uchar channel, uchar note, uchar velocity, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SprayNoteOn(channel - 1, note, velocity, MAKE_BIGTIME(time));
|
||||
fluid_synth_noteon(fSynth, channel - 1, note, velocity);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::KeyPressure(
|
||||
void
|
||||
BSoftSynth::KeyPressure(
|
||||
uchar channel, uchar note, uchar pressure, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SprayKeyPressure(
|
||||
channel - 1, note, pressure, MAKE_BIGTIME(time));
|
||||
// unavailable
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::ControlChange(
|
||||
void
|
||||
BSoftSynth::ControlChange(
|
||||
uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SprayControlChange(
|
||||
channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time));
|
||||
fluid_synth_cc(fSynth, channel - 1, controlNumber, controlValue);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::ProgramChange(
|
||||
void
|
||||
BSoftSynth::ProgramChange(
|
||||
uchar channel, uchar programNumber, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SprayProgramChange(
|
||||
channel - 1, programNumber, MAKE_BIGTIME(time));
|
||||
fluid_synth_program_change(fSynth, channel - 1, programNumber);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::ChannelPressure(uchar channel, uchar pressure, uint32 time)
|
||||
void
|
||||
BSoftSynth::ChannelPressure(uchar channel, uchar pressure, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SprayChannelPressure(
|
||||
channel - 1, pressure, MAKE_BIGTIME(time));
|
||||
//unavailable
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
|
||||
void
|
||||
BSoftSynth::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time));
|
||||
// fluid_synth only accepts an int
|
||||
fluid_synth_pitch_bend(fSynth, channel - 1, ((uint32)(msb & 0x7f) << 8) | (lsb & 0x7f));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::SystemExclusive(void* data, size_t length, uint32 time)
|
||||
void
|
||||
BSoftSynth::SystemExclusive(void* data, size_t length, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SpraySystemExclusive(data, length, MAKE_BIGTIME(time));
|
||||
// unsupported
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::SystemCommon(
|
||||
void
|
||||
BSoftSynth::SystemCommon(
|
||||
uchar status, uchar data1, uchar data2, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time));
|
||||
// unsupported
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::SystemRealTime(uchar status, uint32 time)
|
||||
void
|
||||
BSoftSynth::SystemRealTime(uchar status, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SpraySystemRealTime(status, MAKE_BIGTIME(time));
|
||||
// unsupported
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::TempoChange(int32 beatsPerMinute, uint32 time)
|
||||
void
|
||||
BSoftSynth::TempoChange(int32 beatsPerMinute, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
producer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time));
|
||||
// unsupported
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::AllNotesOff(bool justChannel, uint32 time)
|
||||
void
|
||||
BSoftSynth::AllNotesOff(bool justChannel, uint32 time)
|
||||
{
|
||||
if (InitCheck())
|
||||
{
|
||||
if (InitCheck()) {
|
||||
snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
|
||||
|
||||
// from BMidi::AllNotesOff
|
||||
for (uchar channel = 1; channel <= 16; ++channel)
|
||||
{
|
||||
producer->SprayControlChange(channel, B_ALL_NOTES_OFF, 0, time);
|
||||
for (uchar channel = 1; channel <= 16; ++channel) {
|
||||
fluid_synth_cc(fSynth, channel - 1, B_ALL_NOTES_OFF, 0);
|
||||
|
||||
if (!justChannel)
|
||||
{
|
||||
for (uchar note = 0; note <= 0x7F; ++note)
|
||||
{
|
||||
producer->SprayNoteOff(channel, note, 0, time);
|
||||
if (!justChannel) {
|
||||
for (uchar note = 0; note <= 0x7F; ++note) {
|
||||
fluid_synth_noteoff(fSynth, channel - 1, note);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::Init()
|
||||
void
|
||||
BSoftSynth::Init()
|
||||
{
|
||||
initCheck = false;
|
||||
|
||||
producer = new BMidiLocalProducer("TiMidity feeder");
|
||||
|
||||
int32 id = 0;
|
||||
while ((consumer = BMidiRoster::NextConsumer(&id)) != NULL)
|
||||
{
|
||||
if (strcmp(consumer->Name(), "TiMidity input") == 0)
|
||||
break;
|
||||
|
||||
consumer->Release();
|
||||
}
|
||||
|
||||
if (consumer == NULL)
|
||||
{
|
||||
fprintf(stderr, "[midi] TiMidity consumer not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (producer->Connect(consumer) != B_OK)
|
||||
{
|
||||
fprintf(stderr, "[midi] Could not connect to TiMidity\n");
|
||||
return;
|
||||
}
|
||||
|
||||
initCheck = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void BSoftSynth::Done()
|
||||
{
|
||||
if (consumer != NULL)
|
||||
{
|
||||
producer->Disconnect(consumer);
|
||||
consumer->Release();
|
||||
consumer = NULL;
|
||||
}
|
||||
fInitCheck = false;
|
||||
|
||||
producer->Release();
|
||||
producer = NULL;
|
||||
Done();
|
||||
|
||||
fSettings = new_fluid_settings();
|
||||
fluid_settings_setnum(fSettings, "synth.sample-rate", fSampleRate);
|
||||
fluid_settings_setint(fSettings, "synth.polyphony", fMaxVoices);
|
||||
|
||||
fSynth = new_fluid_synth(fSettings);
|
||||
|
||||
media_raw_audio_format format;
|
||||
format.channel_count = 2;
|
||||
format.frame_rate = fSampleRate;
|
||||
format.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
|
||||
fSoundPlayer = new BSoundPlayer(&format, "softsynth", &PlayBuffer, NULL, this);
|
||||
status_t err = fSoundPlayer->InitCheck();
|
||||
if (err != B_OK)
|
||||
return;
|
||||
|
||||
fSoundPlayer->SetHasData(true);
|
||||
fSoundPlayer->Start();
|
||||
|
||||
fInitCheck = true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BSoftSynth::Done()
|
||||
{
|
||||
if (fSoundPlayer) {
|
||||
fSoundPlayer->SetHasData(false);
|
||||
fSoundPlayer->Stop();
|
||||
delete fSoundPlayer;
|
||||
}
|
||||
if (fSynth)
|
||||
delete_fluid_synth(fSynth);
|
||||
if (fSettings)
|
||||
delete_fluid_settings(fSettings);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BSoftSynth::PlayBuffer(void * cookie, void * data, size_t size, const media_raw_audio_format & format)
|
||||
{
|
||||
BSoftSynth *synth = (BSoftSynth *)cookie;
|
||||
|
||||
// we use float samples
|
||||
|
||||
fluid_synth_write_float(synth->fSynth, size / sizeof(float) / format.channel_count,
|
||||
data, 0, sizeof(float) * format.channel_count,
|
||||
(char *)data + sizeof(float), 0, sizeof(float) * format.channel_count);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
+19
-26
@@ -57,8 +57,11 @@
|
||||
#include <Midi.h>
|
||||
#include <Synth.h>
|
||||
|
||||
#include <SoundPlayer.h>
|
||||
|
||||
#include <fluidsynth.h>
|
||||
|
||||
class BMidiConsumer;
|
||||
class BMidiLocalProducer;
|
||||
class BMidiSynth;
|
||||
class BSynth;
|
||||
|
||||
@@ -68,10 +71,10 @@ class BSoftSynth
|
||||
{
|
||||
public:
|
||||
|
||||
bool InitCheck(void) const;
|
||||
bool InitCheck() const;
|
||||
|
||||
void Unload(void);
|
||||
bool IsLoaded(void) const;
|
||||
void Unload();
|
||||
bool IsLoaded() const;
|
||||
|
||||
status_t SetDefaultInstrumentsFile();
|
||||
status_t SetInstrumentsFile(const char* path);
|
||||
@@ -128,31 +131,21 @@ private:
|
||||
|
||||
void Init();
|
||||
void Done();
|
||||
static void PlayBuffer(void * cookie, void * data, size_t size, const media_raw_audio_format & format);
|
||||
|
||||
bool initCheck;
|
||||
char* instrumentsFile;
|
||||
int32 sampleRate;
|
||||
interpolation_mode interpMode;
|
||||
int16 maxVoices;
|
||||
int16 limiterThreshold;
|
||||
reverb_mode reverbMode;
|
||||
bool reverbEnabled;
|
||||
double volumeScale;
|
||||
bool fInitCheck;
|
||||
char* fInstrumentsFile;
|
||||
int32 fSampleRate;
|
||||
interpolation_mode fInterpMode;
|
||||
int16 fMaxVoices;
|
||||
int16 fLimiterThreshold;
|
||||
reverb_mode fReverbMode;
|
||||
bool fReverbEnabled;
|
||||
|
||||
/*
|
||||
Note: Maybe this isn't the most efficient way to do things.
|
||||
Now a producer connects to BMidiSynth, which is a consumer.
|
||||
That consumer directly calls our NoteOff() etc, methods.
|
||||
We create a new producer and connect it to TiMidity's consumer.
|
||||
It would save some indirection if BMidiSynth's consumer would
|
||||
be a proxy for TiMidity's. (I don't think that is possible,
|
||||
because BMidiSynth is a BMidi object which always creates a
|
||||
new consumer regardless. In any case, notes have to travel
|
||||
a long way before they reach TiMidity.
|
||||
*/
|
||||
fluid_synth_t *fSynth;
|
||||
fluid_settings_t* fSettings;
|
||||
|
||||
BMidiConsumer* consumer;
|
||||
BMidiLocalProducer* producer;
|
||||
BSoundPlayer *fSoundPlayer;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
Reference in New Issue
Block a user