void
fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event)
{
  EVENTFUNC_PTR(fluid_rvoice_mixer_add_voice, fluid_rvoice_mixer_t*, fluid_rvoice_t*);
  EVENTFUNC_I1(fluid_rvoice_noteoff, fluid_rvoice_t*);
  EVENTFUNC_0(fluid_rvoice_voiceoff, fluid_rvoice_t*);
  EVENTFUNC_0(fluid_rvoice_reset, fluid_rvoice_t*);

  EVENTFUNC_ALL(fluid_adsr_env_set_data, fluid_adsr_env_t*);

  EVENTFUNC_I1(fluid_lfo_set_delay, fluid_lfo_t*);
  EVENTFUNC_R1(fluid_lfo_set_incr, fluid_lfo_t*);

  EVENTFUNC_R1(fluid_iir_filter_set_fres, fluid_iir_filter_t*);
  EVENTFUNC_R1(fluid_iir_filter_set_q_dB, fluid_iir_filter_t*);

  EVENTFUNC_IR(fluid_rvoice_buffers_set_mapping, fluid_rvoice_buffers_t*);
  EVENTFUNC_IR(fluid_rvoice_buffers_set_amp, fluid_rvoice_buffers_t*);

  EVENTFUNC_R1(fluid_rvoice_set_modenv_to_pitch, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_output_rate, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_root_pitch_hz, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_synth_gain, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_pitch, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_attenuation, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_min_attenuation_cB, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_viblfo_to_pitch, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_modlfo_to_pitch, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_modlfo_to_vol, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_modlfo_to_fc, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_modenv_to_fc, fluid_rvoice_t*);
  EVENTFUNC_R1(fluid_rvoice_set_modenv_to_pitch, fluid_rvoice_t*);
  EVENTFUNC_I1(fluid_rvoice_set_interp_method, fluid_rvoice_t*);
  EVENTFUNC_I1(fluid_rvoice_set_start, fluid_rvoice_t*);
  EVENTFUNC_I1(fluid_rvoice_set_end, fluid_rvoice_t*);
  EVENTFUNC_I1(fluid_rvoice_set_loopstart, fluid_rvoice_t*);
  EVENTFUNC_I1(fluid_rvoice_set_loopend, fluid_rvoice_t*);
  EVENTFUNC_I1(fluid_rvoice_set_samplemode, fluid_rvoice_t*);
  EVENTFUNC_PTR(fluid_rvoice_set_sample, fluid_rvoice_t*, fluid_sample_t*);

  EVENTFUNC_R1(fluid_rvoice_mixer_set_samplerate, fluid_rvoice_mixer_t*);
  EVENTFUNC_I1(fluid_rvoice_mixer_set_polyphony, fluid_rvoice_mixer_t*);
  EVENTFUNC_I1(fluid_rvoice_mixer_set_reverb_enabled, fluid_rvoice_mixer_t*);
  EVENTFUNC_I1(fluid_rvoice_mixer_set_chorus_enabled, fluid_rvoice_mixer_t*);
  EVENTFUNC_I1(fluid_rvoice_mixer_set_mix_fx, fluid_rvoice_mixer_t*);
  EVENTFUNC_0(fluid_rvoice_mixer_reset_fx, fluid_rvoice_mixer_t*);
  EVENTFUNC_0(fluid_rvoice_mixer_reset_reverb, fluid_rvoice_mixer_t*);
  EVENTFUNC_0(fluid_rvoice_mixer_reset_chorus, fluid_rvoice_mixer_t*);
  EVENTFUNC_IR(fluid_rvoice_mixer_set_threads, fluid_rvoice_mixer_t*);
 
  EVENTFUNC_ALL(fluid_rvoice_mixer_set_chorus_params, fluid_rvoice_mixer_t*);
  EVENTFUNC_R4(fluid_rvoice_mixer_set_reverb_params, fluid_rvoice_mixer_t*);

  FLUID_LOG(FLUID_ERR, "fluid_rvoice_event_dispatch: Unknown method %p to dispatch!", event->method);
}
Example #2
0
void *
fluid_sndio_midi_run(void *addr)
{
  int n, i;
  fluid_midi_event_t* evt;
  fluid_sndio_midi_driver_t *dev = (fluid_sndio_midi_driver_t *)addr;
#define MIDI_BUFLEN (3125 / 10)
  unsigned char buffer[MIDI_BUFLEN];

  /* make sure the other threads can cancel this thread any time */
  if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) {
    FLUID_LOG(FLUID_ERR, "Failed to set the cancel state of the midi thread");
    pthread_exit(NULL);
  }
  if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
    FLUID_LOG(FLUID_ERR, "Failed to set the cancel state of the midi thread");
    pthread_exit(NULL);
  }

  /* go into a loop until someone tells us to stop */
  dev->status = FLUID_MIDI_LISTENING;

  while (dev->status == FLUID_MIDI_LISTENING) {

    /* read new data */
    n = mio_read(dev->hdl, buffer, MIDI_BUFLEN);
    if (n == 0 && mio_eof(dev->hdl)) {
      FLUID_LOG(FLUID_ERR, "Failed to read the midi input");
      dev->status = FLUID_MIDI_DONE;
    }

    /* let the parser convert the data into events */
    for (i = 0; i < n; i++) {
      evt = fluid_midi_parser_parse(dev->parser, buffer[i]);
      if (evt != NULL) {
	/* send the event to the next link in the chain */
	(*dev->driver.handler)(dev->driver.data, evt);
      }
    }
  }
  pthread_exit(NULL);
}
Example #3
0
void
fluid_portaudio_driver_settings (fluid_settings_t *settings)
{
  const PaDeviceInfo *deviceInfo;
  int numDevices;
  PaError err;
  int i;

  fluid_settings_register_str (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE, 0, NULL, NULL);
  fluid_settings_add_option (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE);

  err = Pa_Initialize();

  if (err != paNoError)
  {
    FLUID_LOG (FLUID_ERR, "Error initializing PortAudio driver: %s",
               Pa_GetErrorText (err));
    return;
  }

  numDevices = Pa_GetDeviceCount();

  if (numDevices < 0)
  {
    FLUID_LOG (FLUID_ERR, "PortAudio returned unexpected device count %d", numDevices);
    return;
  }

  for (i = 0; i < numDevices; i++)
  {
    deviceInfo = Pa_GetDeviceInfo (i);
    if ( deviceInfo->maxOutputChannels >= 2 )
      fluid_settings_add_option (settings, "audio.portaudio.device",
                                 deviceInfo->name);
  }

  /* done with PortAudio for now, may get reopened later */
  err = Pa_Terminate();

  if (err != paNoError)
    printf ("PortAudio termination error: %s\n", Pa_GetErrorText (err) );
}
Example #4
0
/*
 * new_fluid_midi_parser
 */
fluid_midi_parser_t* new_fluid_midi_parser()
{
	fluid_midi_parser_t* parser;
	parser = FLUID_NEW(fluid_midi_parser_t);
	if (parser == NULL) {
		FLUID_LOG(FLUID_ERR, "Out of memory");
		return NULL;
	}
	parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */
	return parser;
}
Example #5
0
void fluid_profiling_print(void)
{
  int i;

  printf("fluid_profiling_print\n");

  FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)");

  for (i = 0; i < FLUID_PROF_LAST; i++) {
    if (fluid_profile_data[i].count > 0) {
      FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f",
	       fluid_profile_data[i].description,
	       fluid_profile_data[i].min,
	       fluid_profile_data[i].total / fluid_profile_data[i].count,
	       fluid_profile_data[i].max);
    } else {
      FLUID_LOG(FLUID_DBG, "%s: no profiling available", fluid_profile_data[i].description);
    }
  }
}
Example #6
0
int fluid_samplecache_load(SFData *sf,
                           unsigned int sample_start, unsigned int sample_end, int sample_type,
                           int try_mlock, short **sample_data, char **sample_data24)
{
    fluid_samplecache_entry_t *entry;
    int ret;

    fluid_mutex_lock(samplecache_mutex);

    entry = get_samplecache_entry(sf, sample_start, sample_end, sample_type);
    if (entry == NULL)
    {
        entry = new_samplecache_entry(sf, sample_start, sample_end, sample_type);
        if (entry == NULL)
        {
            ret = -1;
            goto unlock_exit;
        }

        samplecache_list = fluid_list_prepend(samplecache_list, entry);
    }

    if (try_mlock && !entry->mlocked)
    {
        /* Lock the memory to disable paging. It's okay if this fails. It
         * probably means that the user doesn't have the required permission. */
        if (fluid_mlock(entry->sample_data, entry->sample_count * sizeof(short)) == 0)
        {
            if (entry->sample_data24 != NULL)
            {
                entry->mlocked = (fluid_mlock(entry->sample_data24, entry->sample_count) == 0);
            }
            else
            {
                entry->mlocked = TRUE;
            }

            if (!entry->mlocked)
            {
                fluid_munlock(entry->sample_data, entry->sample_count * sizeof(short));
                FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible.");
            }
        }
    }

    entry->num_references++;
    *sample_data = entry->sample_data;
    *sample_data24 = entry->sample_data24;
    ret = entry->sample_count;

unlock_exit:
    fluid_mutex_unlock(samplecache_mutex);
    return ret;
}
Example #7
0
/*
 * fluid_midi_file_read
 */
int fluid_midi_file_read(fluid_midi_file* mf, void* buf, int len)
{
	int num = FLUID_FREAD(buf, 1, len, mf->fp);
	mf->trackpos += num;
#if DEBUG
	if (num != len) {
		FLUID_LOG(FLUID_DBG, "Coulnd't read the requested number of bytes");
	}
#endif
	return (num != len)? FLUID_FAILED : FLUID_OK;
}
Example #8
0
/**
 * Set the tempo of a MIDI player.
 * @param player MIDI player instance
 * @param tempo Tempo to set playback speed to (in microseconds per quarter note, as per MIDI file spec)
 * @return Always returns #FLUID_OK
 */
int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo)
{
	player->miditempo = tempo;
	player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
	player->start_msec = player->cur_msec;
	player->start_ticks = player->cur_ticks;

	FLUID_LOG(FLUID_DBG,"tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
		  tempo, player->deltatime, player->cur_msec, player->cur_ticks);

	return FLUID_OK;
}
Example #9
0
/**
 * Create a new thread.
 * @param func Function to execute in new thread context
 * @param data User defined data to pass to func
 * @param prio_level Priority level.  If greater than 0 then high priority scheduling will
 *   be used, with the given priority level (used by pthreads only).  0 uses normal scheduling.
 * @param detach If TRUE, 'join' does not work and the thread destroys itself when finished.
 * @return New thread pointer or NULL on error
 */
fluid_thread_t *
new_fluid_thread (fluid_thread_func_t func, void *data, int prio_level, int detach)
{
  GThread *thread;
  fluid_thread_info_t *info;
  GError *err = NULL;

  g_return_val_if_fail (func != NULL, NULL);

  /* Make sure g_thread_init has been called.
   * FIXME - Probably not a good idea in a shared library,
   * but what can we do *and* remain backwards compatible? */
  if (!g_thread_supported ()) g_thread_init (NULL);

  if (prio_level > 0)
  {
    info = FLUID_NEW (fluid_thread_info_t);

    if (!info)
    {
      FLUID_LOG(FLUID_ERR, "Out of memory");
      return NULL;
    }

    info->func = func;
    info->data = data;
    info->prio_level = prio_level;
    thread = g_thread_create (fluid_thread_high_prio, info, detach == FALSE, &err);
  }
  else thread = g_thread_create ((GThreadFunc)func, data, detach == FALSE, &err);

  if (!thread)
  {
    FLUID_LOG(FLUID_ERR, "Failed to create the thread: %s",
              fluid_gerror_message (err));
    g_clear_error (&err);
  }

  return thread;
}
Example #10
0
/*
 * new_fluid_sndmgr_audio_driver2
 *
 * This implementation used the audio_func float format, with
 * conversion from float to 16bits in the driver.
 */
fluid_audio_driver_t*
new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
{
  fluid_sndmgr_audio_driver_t* dev = NULL;
  int period_size, periods, buffer_size;

  /* compute buffer size */
  fluid_settings_getint(settings, "audio.period-size", &period_size);
  fluid_settings_getint(settings, "audio.periods", &periods);
  buffer_size = period_size*periods;

  /* allocated dev */
  dev = FLUID_NEW(fluid_sndmgr_audio_driver_t);
  if (dev == NULL) {
    FLUID_LOG(FLUID_PANIC, "Out of memory");
    return NULL;
  }
  FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t));

  /* allocate the conversion buffers */
  dev->convbuffers[0] = FLUID_ARRAY(float, buffer_size);
  dev->convbuffers[1] = FLUID_ARRAY(float, buffer_size);
  if ((dev->convbuffers[0] == NULL) || (dev->convbuffers[1] == NULL)) {
    FLUID_LOG(FLUID_PANIC, "Out of memory");
    goto error_recovery;
  }

  dev->callback_is_audio_func = true;
  dev->data = data;
  dev->callback = func;

  if (start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) {
    goto error_recovery;
  }
  return (fluid_audio_driver_t*)dev;

 error_recovery:
  delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t*)dev);
  return NULL;
}
Example #11
0
fluid_audio_driver_t*
new_fluid_file_audio_driver(fluid_settings_t* settings,
			    fluid_synth_t* synth)
{
	fluid_file_audio_driver_t* dev;
	int msec;

	dev = FLUID_NEW(fluid_file_audio_driver_t);
	if (dev == NULL) {
		FLUID_LOG(FLUID_ERR, "Out of memory");
		return NULL;
	}
	FLUID_MEMSET(dev, 0, sizeof(fluid_file_audio_driver_t));

	fluid_settings_getint(settings, "audio.period-size", &dev->period_size);
	fluid_settings_getnum(settings, "synth.sample-rate", &dev->sample_rate);

	dev->data = synth;
	dev->callback = (fluid_audio_func_t) fluid_synth_process;
	dev->samples = 0;

	dev->renderer = new_fluid_file_renderer(synth);

	if (dev->renderer == NULL)
		goto error_recovery;

	msec = (int) (0.5 + dev->period_size / dev->sample_rate * 1000.0);
	dev->timer = new_fluid_timer(msec, fluid_file_audio_run_s16, (void*) dev, TRUE, FALSE, TRUE);
	if (dev->timer == NULL) {
		FLUID_LOG(FLUID_PANIC, "Couldn't create the audio thread.");
		goto error_recovery;
	}

	return (fluid_audio_driver_t*) dev;

 error_recovery:
	delete_fluid_file_audio_driver((fluid_audio_driver_t*) dev);
	return NULL;
}
Example #12
0
/*
 * fluid_hashtable_insert_internal:
 * @hashtable: our #fluid_hashtable_t
 * @key: the key to insert
 * @value: the value to insert
 * @keep_new_key: if %TRUE and this key already exists in the table
 *   then call the destroy notify function on the old key.  If %FALSE
 *   then call the destroy notify function on the new key.
 *
 * Implements the common logic for the fluid_hashtable_insert() and
 * fluid_hashtable_replace() functions.
 *
 * Do a lookup of @key.  If it is found, replace it with the new
 * @value (and perhaps the new @key).  If it is not found, create a
 * new node.
 */
static void
fluid_hashtable_insert_internal (fluid_hashtable_t *hashtable, void *key,
                                 void *value, int keep_new_key)
{
  fluid_hashnode_t **node_ptr, *node;
  unsigned int key_hash;

  fluid_return_if_fail (hashtable != NULL);
  fluid_return_if_fail (hashtable->ref_count > 0);

  node_ptr = fluid_hashtable_lookup_node (hashtable, key, &key_hash);

  if ((node = *node_ptr))
    {
      if (keep_new_key)
        {
          if (hashtable->key_destroy_func)
            hashtable->key_destroy_func (node->key);
          node->key = key;
        }
      else
        {
          if (hashtable->key_destroy_func)
            hashtable->key_destroy_func (key);
        }

      if (hashtable->value_destroy_func)
        hashtable->value_destroy_func (node->value);

      node->value = value;
    }
  else
    {
      node = FLUID_NEW (fluid_hashnode_t);

      if (!node)
      {
        FLUID_LOG (FLUID_ERR, "Out of memory");
        return;
      }

      node->key = key;
      node->value = value;
      node->key_hash = key_hash;
      node->next = NULL;

      *node_ptr = node;
      hashtable->nnodes++;
      fluid_hashtable_maybe_resize (hashtable);
    }
}
Example #13
0
/*
 * fluid_midishare_open_appl
 */
static int fluid_midishare_open_appl (fluid_midishare_midi_driver_t* dev)
{
    /* register to MidiShare */
#if defined(MACINTOSH) && defined(MACOS9)
    dev->refnum = MidiOpen(MSHDriverName);
    if (dev->refnum < 0) {
        FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client");
        return 0;
    }
    dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive);
    dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task);
    MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr);
#else
    dev->refnum = MidiOpen(MSHDriverName);
    if (dev->refnum < 0) {
        FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client");
        return 0;
    }
    MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive);
    MidiConnect(0,dev->refnum,true);
#endif
    return 1;
}
/* Duplicate a tuning */
fluid_tuning_t *
fluid_tuning_duplicate (fluid_tuning_t *tuning)
{
  fluid_tuning_t *new_tuning;
  int i;

  new_tuning = FLUID_NEW (fluid_tuning_t);

  if (!new_tuning) {
    FLUID_LOG (FLUID_PANIC, "Out of memory");
    return NULL;
  }

  if (tuning->name)
  {
    new_tuning->name = FLUID_STRDUP (tuning->name);

    if (!new_tuning->name)
    {
      FLUID_FREE (new_tuning);
      FLUID_LOG (FLUID_PANIC, "Out of memory");
      return NULL;
    }
  }
  else new_tuning->name = NULL;

  new_tuning->bank = tuning->bank;
  new_tuning->prog = tuning->prog;

  for (i = 0; i < 128; i++)
    new_tuning->pitch[i] = tuning->pitch[i];

  new_tuning->refcount = 1;     /* Start with a refcount of 1 */

  return new_tuning;
}
Example #15
0
/*
 * fluid_midi_file_skip
 */
int
fluid_midi_file_skip (fluid_midi_file *mf, int skip)
{
    int new_pos = mf->buf_pos + skip;
    /* Mimic the behaviour of fseek: Error to seek past the start of file, but
     * OK to seek past end (this just puts it into the EOF state). */
    if (new_pos < 0) {
        FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
        return FLUID_FAILED;
    }
    /* Clear the EOF flag, even if moved past the end of the file (this is
     * consistent with the behaviour of fseek). */
    mf->eof = FALSE;
    mf->buf_pos = new_pos;
    return FLUID_OK;
}
Example #16
0
/*
 * fluid_player_callback
 */
int
fluid_player_callback(void *data, unsigned int msec)
{
    int i;
    int loadnextfile;
    int status = FLUID_PLAYER_DONE;
    fluid_player_t *player;
    fluid_synth_t *synth;
    player = (fluid_player_t *) data;
    synth = player->synth;

    loadnextfile = player->currentfile == NULL ? 1 : 0;
    do {
        if (loadnextfile) {
            loadnextfile = 0;
            fluid_player_playlist_load(player, msec);
            if (player->currentfile == NULL) {
                return 0;
            }
        }

        player->cur_msec = msec;
        player->cur_ticks = (player->start_ticks
                + (int) ((double) (player->cur_msec - player->start_msec)
                        / player->deltatime));

        for (i = 0; i < player->ntracks; i++) {
            if (!fluid_track_eot(player->track[i])) {
                status = FLUID_PLAYER_PLAYING;
                if (fluid_track_send_events(player->track[i], synth, player,
                        player->cur_ticks) != FLUID_OK) {
                    /* */
                }
            }
        }

        if (status == FLUID_PLAYER_DONE) {
            FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__,
                    __LINE__, (msec - player->begin_msec) / 1000.0);
            loadnextfile = 1;
        }
    } while (loadnextfile);

    player->status = status;

    return 1;
}
Example #17
0
int fluid_samplecache_unload(const short *sample_data)
{
    fluid_list_t *entry_list;
    fluid_samplecache_entry_t *entry;
    int ret;

    fluid_mutex_lock(samplecache_mutex);

    entry_list = samplecache_list;
    while (entry_list)
    {
        entry = (fluid_samplecache_entry_t *)fluid_list_get(entry_list);

        if (sample_data == entry->sample_data)
        {
            entry->num_references--;

            if (entry->num_references == 0)
            {
                if (entry->mlocked)
                {
                    fluid_munlock(entry->sample_data, entry->sample_count * sizeof(short));
                    if (entry->sample_data24 != NULL)
                    {
                        fluid_munlock(entry->sample_data24, entry->sample_count);
                    }
                }

                samplecache_list = fluid_list_remove(samplecache_list, entry);
                delete_samplecache_entry(entry);
            }

            ret = FLUID_OK;
            goto unlock_exit;
        }

        entry_list = fluid_list_next(entry_list);
    }

    FLUID_LOG(FLUID_ERR, "Trying to free sample data not found in cache.");
    ret = FLUID_FAILED;

unlock_exit:
    fluid_mutex_unlock(samplecache_mutex);
    return ret;
}
Example #18
0
/**
 * Create a MIDI event structure.
 * @return New MIDI event structure or NULL when out of memory.
 */
fluid_midi_event_t* new_fluid_midi_event()
{
	fluid_midi_event_t* evt;
	evt = FLUID_NEW(fluid_midi_event_t);
	if (evt == NULL) {
		FLUID_LOG(FLUID_ERR, "Out of memory");
		return NULL;
	}
	evt->dtime = 0;
	evt->type = 0;
	evt->channel = 0;
	evt->param1 = 0;
	evt->param2 = 0;
	evt->next = NULL;
	evt->paramptr = NULL;
	return evt;
}
Example #19
0
/**
 * Add a MIDI file to a player queue.
 * @param player MIDI player instance
 * @param midifile File name of the MIDI file to add
 * @return #FLUID_OK or #FLUID_FAILED
 */
int
fluid_player_add(fluid_player_t *player, const char *midifile)
{
    fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
    char* f = FLUID_STRDUP(midifile);
    if (!pi || !f) {
        FLUID_FREE(pi);
        FLUID_FREE(f);
        FLUID_LOG(FLUID_PANIC, "Out of memory");
        return FLUID_FAILED;
    }

    pi->filename = f;
    pi->buffer = NULL;
    pi->buffer_len = 0;
    player->playlist = fluid_list_append(player->playlist, pi);
    return FLUID_OK;
}
Example #20
0
/** returns 1 if the value has been register correctly, zero
    otherwise. */
int
fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
			    int min, int max, int hints,
			    fluid_int_update_t fun, void* data)
{
  fluid_setting_node_t *node;
  int retval;

  fluid_return_val_if_fail (settings != NULL, 0);
  fluid_return_val_if_fail (name != NULL, 0);

  /* For now, all integer settings are bounded below and above */
  hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;

  fluid_rec_mutex_lock (settings->mutex);

  if (!fluid_settings_get(settings, name, &node)) {
    /* insert a new setting */
    fluid_int_setting_t* setting;
    setting = new_fluid_int_setting(min, max, def, hints, fun, data);
    retval = fluid_settings_set(settings, name, setting);
    if (retval != 1) delete_fluid_int_setting (setting);
  } else {
    if (node->type == FLUID_INT_TYPE) {
      /* update the existing setting but don't change its value */
      fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
      setting->update = fun;
      setting->data = data;
      setting->min = min;
      setting->max = max;
      setting->def = def;
      setting->hints = hints;
      retval = 1;
    } else {
      /* type mismatch */
      FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
      retval = 0;
    }
  }

  fluid_rec_mutex_unlock (settings->mutex);

  return retval;
}
Example #21
0
/*
 * fluid_track_set_name
 */
int fluid_track_set_name(fluid_track_t* track, char* name)
{
	int len;
	if (track->name != NULL) {
		FLUID_FREE(track->name);
	}
	if (name == NULL) {
		track->name = NULL;
		return FLUID_OK;
	}
	len = FLUID_STRLEN(name);
	track->name = FLUID_MALLOC(len + 1);
	if (track->name == NULL) {
		FLUID_LOG(FLUID_ERR, "Out of memory");
		return FLUID_FAILED;
	}
	FLUID_STRCPY(track->name, name);
	return FLUID_OK;
}
Example #22
0
/**
 * Add a MIDI file to a player queue, from a buffer in memory.
 * @param player MIDI player instance
 * @param buffer Pointer to memory containing the bytes of a complete MIDI
 *   file. The data is copied, so the caller may free or modify it immediately
 *   without affecting the playlist.
 * @param len Length of the buffer, in bytes.
 * @return #FLUID_OK or #FLUID_FAILED
 */
int
fluid_player_add_mem(fluid_player_t* player, const void *buffer, size_t len)
{
    /* Take a copy of the buffer, so the caller can free immediately. */
    fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
    void *buf_copy = FLUID_MALLOC(len);
    if (!pi || !buf_copy) {
        FLUID_FREE(pi);
        FLUID_FREE(buf_copy);
        FLUID_LOG(FLUID_PANIC, "Out of memory");
        return FLUID_FAILED;
    }

    FLUID_MEMCPY(buf_copy, buffer, len);
    pi->filename = NULL;
    pi->buffer = buf_copy;
    pi->buffer_len = len;
    player->playlist = fluid_list_append(player->playlist, pi);
    return FLUID_OK;
}
Example #23
0
/*
 * new_fluid_channel
 */
fluid_channel_t*
new_fluid_channel(fluid_synth_t* synth, int num)
{
  fluid_channel_t* chan;

  chan = FLUID_NEW(fluid_channel_t);
  if (chan == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }

  chan->synth = synth;
  chan->channum = num;
  chan->preset = NULL;

  fluid_channel_init(chan);
  fluid_channel_init_ctrl(chan);

  return chan;
}
Example #24
0
BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
  FLUID_LOG(FLUID_DBG, "DllMain");
  switch (ul_reason_for_call) {
  case DLL_PROCESS_ATTACH:
    fluid_refCount++;
    if (1 == fluid_refCount) {
      fluid_set_hinstance((void*) hModule);
      fluid_win32_create_window();
    }
    break;
  case DLL_PROCESS_DETACH:
    fluid_refCount--;
    if (fluid_refCount == 0) {
      fluid_win32_destroy_window();
    }
    break;
  }
  return TRUE;
}
Example #25
0
/*
 * fluid_sndio_audio_run
 */
void*
fluid_sndio_audio_run(void* d)
{
  fluid_sndio_audio_driver_t* dev = (fluid_sndio_audio_driver_t*) d;
  fluid_synth_t* synth = dev->synth;
  void* buffer = dev->buffer;
  int len = dev->buffer_size;

  /* it's as simple as that: */
  while (dev->cont)
  {
    dev->read (synth, len, buffer, 0, 2, buffer, 1, 2);
    sio_write (dev->hdl, buffer, dev->buffer_byte_size);
  }

  FLUID_LOG(FLUID_DBG, "Audio thread finished");

  pthread_exit(NULL);

  return 0; /* not reached */
}
Example #26
0
/* Purpose:
 * Checks, if the floating point unit has produced an exception, print a message
 * if so and clear the exception.
 */
unsigned int fluid_check_fpe_i386(char* explanation)
{
  unsigned int s;

  _FPU_GET_SW(s);
  _FPU_CLR_SW();

  s &= _FPU_STATUS_IE | _FPU_STATUS_DE | _FPU_STATUS_ZE | _FPU_STATUS_OE | _FPU_STATUS_UE;

  if (s)
  {
      FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation,
	       (s & _FPU_STATUS_IE) ? "Invalid operation " : "",
	       (s & _FPU_STATUS_DE) ? "Denormal number " : "",
	       (s & _FPU_STATUS_ZE) ? "Zero divide " : "",
	       (s & _FPU_STATUS_OE) ? "Overflow " : "",
	       (s & _FPU_STATUS_UE) ? "Underflow " : "");
  }

  return s;
}
Example #27
0
/**
 * Create a new midi router.  The default rules will pass all events unmodified.
 * @param settings Settings used to configure MIDI router
 * @param handler MIDI event callback.
 * @param event_handler_data Caller defined data pointer which gets passed to 'handler'
 * @return New MIDI router instance or NULL on error
 *
 * The MIDI handler callback should process the possibly filtered/modified MIDI
 * events from the MIDI router and forward them on to a synthesizer for example.
 * The function fluid_synth_handle_midi_event() can be used for \a handle and
 * a #fluid_synth_t passed as the \a event_handler_data parameter for this purpose.
 */
fluid_midi_router_t *
new_fluid_midi_router(fluid_settings_t *settings, handle_midi_event_func_t handler,
                      void *event_handler_data)
{
  fluid_midi_router_t *router = NULL;
  int i;

  router = FLUID_NEW (fluid_midi_router_t);

  if (router == NULL)
  {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }

  FLUID_MEMSET (router, 0, sizeof (fluid_midi_router_t));

  /* Retrieve the number of MIDI channels for range limiting */
  fluid_settings_getint(settings, "synth.midi-channels", &router->nr_midi_channels);

  fluid_mutex_init (router->rules_mutex);

  router->synth = (fluid_synth_t *)event_handler_data;
  router->event_handler = handler;
  router->event_handler_data = event_handler_data;

  /* Create default routing rules which pass all events unmodified */
  for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
  {
    router->rules[i] = new_fluid_midi_router_rule ();
    if (!router->rules[i]) goto error_recovery;
  }

  return router;

 error_recovery:
  delete_fluid_midi_router (router);
  return NULL;
}
Example #28
0
static fluid_str_setting_t*
new_fluid_str_setting(const char* value, char* def, int hints, fluid_str_update_t fun, void* data)
{
  fluid_str_setting_t* str;

  str = FLUID_NEW(fluid_str_setting_t);

  if (!str)
  {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }

  str->node.type = FLUID_STR_TYPE;
  str->value = value? FLUID_STRDUP(value) : NULL;
  str->def = def? FLUID_STRDUP(def) : NULL;
  str->hints = hints;
  str->options = NULL;
  str->update = fun;
  str->data = data;
  return str;
}
Example #29
0
/*
 * fluid_hashtable_resize:
 * @hashtable: our #fluid_hashtable_t
 *
 * Resizes the hash table to the optimal size based on the number of
 * nodes currently held.  If you call this function then a resize will
 * occur, even if one does not need to occur.  Use
 * fluid_hashtable_maybe_resize() instead.
 */
static void
fluid_hashtable_resize (fluid_hashtable_t *hashtable)
{
  fluid_hashnode_t **new_nodes;
  fluid_hashnode_t *node;
  fluid_hashnode_t *next;
  unsigned int hash_val;
  int new_size;
  int i;

  new_size = spaced_primes_closest (hashtable->nnodes);
  new_size = (new_size < HASH_TABLE_MIN_SIZE) ? HASH_TABLE_MIN_SIZE :
    ((new_size > HASH_TABLE_MAX_SIZE) ? HASH_TABLE_MAX_SIZE : new_size);

  new_nodes = FLUID_ARRAY (fluid_hashnode_t *, new_size);

  if (!new_nodes)
  {
    FLUID_LOG (FLUID_ERR, "Out of memory");
    return;
  }

  FLUID_MEMSET (new_nodes, 0, new_size * sizeof (fluid_hashnode_t *));

  for (i = 0; i < hashtable->size; i++)
    for (node = hashtable->nodes[i]; node; node = next)
      {
	next = node->next;

	hash_val = node->key_hash % new_size;

	node->next = new_nodes[hash_val];
	new_nodes[hash_val] = node;
      }

  FLUID_FREE (hashtable->nodes);
  hashtable->nodes = new_nodes;
  hashtable->size = new_size;
}
Example #30
0
/**
 * Create a new thread.
 * @param func Function to execute in new thread context
 * @param data User defined data to pass to func
 * @param prio_level Priority level.  If greater than 0 then high priority scheduling will
 *   be used, with the given priority level (used by pthreads only).  0 uses normal scheduling.
 * @param detach If TRUE, 'join' does not work and the thread destroys itself when finished.
 * @return New thread pointer or NULL on error
 */
fluid_thread_t *
new_fluid_thread (const char *name, fluid_thread_func_t func, void *data, int prio_level, int detach)
{
  GThread *thread;
  fluid_thread_info_t *info;
  GError *err = NULL;

  g_return_val_if_fail (func != NULL, NULL);

#if OLD_GLIB_THREAD_API
  /* Make sure g_thread_init has been called.
   * FIXME - Probably not a good idea in a shared library,
   * but what can we do *and* remain backwards compatible? */
  if (!g_thread_supported ()) g_thread_init (NULL);
#endif

  if (prio_level > 0)
  {
    info = FLUID_NEW (fluid_thread_info_t);

    if (!info)
    {
      FLUID_LOG(FLUID_ERR, "Out of memory");
      return NULL;
    }

    info->func = func;
    info->data = data;
    info->prio_level = prio_level;
#if NEW_GLIB_THREAD_API
    thread = g_thread_try_new (name, fluid_thread_high_prio, info, &err);
#else
    thread = g_thread_create (fluid_thread_high_prio, info, detach == FALSE, &err);
#endif
  }
#if NEW_GLIB_THREAD_API
  else thread = g_thread_try_new (name, (GThreadFunc)func, data, &err);
#else
  else thread = g_thread_create ((GThreadFunc)func, data, detach == FALSE, &err);