Beispiel #1
0
/**
 * Register a sequencer client.
 * @param seq Sequencer object
 * @param name Name of sequencer client
 * @param callback Sequencer client callback or NULL for a source client.
 * @param data User data to pass to the \a callback
 * @return Unique sequencer ID or #FLUID_FAILED on error
 *
 * Clients can be sources or destinations of events.  Sources don't need to
 * register a callback.
 */
short
fluid_sequencer_register_client (fluid_sequencer_t* seq, const char *name,
                                 fluid_event_callback_t callback, void* data)
{
	fluid_sequencer_client_t * client;
	char * nameCopy;

	client = FLUID_NEW(fluid_sequencer_client_t);
	if (client == NULL) {
		fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
		return FLUID_FAILED;
	}

	nameCopy = FLUID_STRDUP(name);
	if (nameCopy == NULL) {
		fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
		FLUID_FREE(client);
		return FLUID_FAILED;
	}

	seq->clientsID++;

	client->name = nameCopy;
	client->id = seq->clientsID;
	client->callback = callback;
	client->data = data;

	seq->clients = fluid_list_append(seq->clients, (void *)client);

	return (client->id);
}
Beispiel #2
0
fluid_evt_heap_t*
_fluid_evt_heap_init(int nbEvents)
{
#ifdef HEAP_WITH_DYNALLOC

  int i;
  fluid_evt_heap_t* heap;
  fluid_evt_entry *tmp;

  heap = FLUID_NEW(fluid_evt_heap_t);
  if (heap == NULL) {
    fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
    return NULL;
  }

  heap->freelist = NULL;
  fluid_mutex_init(heap->mutex);

  /* LOCK */
  fluid_mutex_lock(heap->mutex);

  /* Allocate the event entries */
  for (i = 0; i < nbEvents; i++) {
    tmp = FLUID_NEW(fluid_evt_entry);
    tmp->next = heap->freelist;
    heap->freelist = tmp;
  }

  /* UNLOCK */
  fluid_mutex_unlock(heap->mutex);


#else
	int i;
	fluid_evt_heap_t* heap;
	int siz = 2*sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry)*nbEvents;

	heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz);
  if (heap == NULL) {
    fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
    return NULL;
  }
  FLUID_MEMSET(heap, 0, siz);

  /* link all heap events */
  {
  	fluid_evt_entry *tmp = &(heap->pool);
	  for (i = 0 ; i < nbEvents - 1 ; i++)
 		 	tmp[i].next = &(tmp[i+1]);
 	 	tmp[nbEvents-1].next = NULL;

 	 	/* set head & tail */
 	 	heap->tail = &(tmp[nbEvents-1]);
  	heap->head = &(heap->pool);
  }
#endif
  return (heap);
}
Beispiel #3
0
/* Create event_entry and append to the preQueue.
 * May be called from the main thread (usually) but also recursively
 * from the queue thread, when a callback itself does an insert... */
static void
_fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int type)
{
	fluid_evt_entry * evtentry = _fluid_seq_heap_get_free(seq->heap);
	if (evtentry == NULL) {
		/* should not happen */
		fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
		return;
	}

	evtentry->next = NULL;
	evtentry->entryType = FLUID_EVT_ENTRY_REMOVE;
	{
		fluid_event_t* evt = &(evtentry->evt);
		fluid_event_set_source(evt, src);
		fluid_event_set_source(evt, src);
		fluid_event_set_dest(evt, dest);
		evt->type = type;
	}

	fluid_mutex_lock(seq->mutex);

	/* append to preQueue */
	if (seq->preQueueLast) {
		seq->preQueueLast->next = evtentry;
	} else {
		seq->preQueue = evtentry;
	}
	seq->preQueueLast = evtentry;

	fluid_mutex_unlock(seq->mutex);
	return;
}
Beispiel #4
0
/* Create event_entry and append to the preQueue.
 * May be called from the main thread (usually) but also recursively
 * from the queue thread, when a callback itself does an insert... */
static short
_fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt)
{
	fluid_evt_entry * evtentry = _fluid_seq_heap_get_free(seq->heap);
	if (evtentry == NULL) {
		/* should not happen */
		fluid_log(FLUID_PANIC, "sequencer: no more free events\n");
		return -1;
	}

	evtentry->next = NULL;
	evtentry->entryType = FLUID_EVT_ENTRY_INSERT;
	FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t));

	fluid_mutex_lock(seq->mutex);

	/* append to preQueue */
	if (seq->preQueueLast) {
		seq->preQueueLast->next = evtentry;
	} else {
		seq->preQueue = evtentry;
	}
	seq->preQueueLast = evtentry;

	fluid_mutex_unlock(seq->mutex);

	return (0);
}
Beispiel #5
0
static short
_fluid_seq_queue_init(fluid_sequencer_t* seq, int maxEvents)
{
	seq->heap = _fluid_evt_heap_init(maxEvents);
	if (seq->heap == NULL) {
		fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
		return -1;
	}

	seq->preQueue = NULL;
	seq->preQueueLast = NULL;

	FLUID_MEMSET(seq->queue0, 0, 2*256*sizeof(fluid_evt_entry *));
	FLUID_MEMSET(seq->queue1, 0, 2*255*sizeof(fluid_evt_entry *));

	seq->queueLater = NULL;
	seq->queue0StartTime = fluid_sequencer_get_tick(seq);
	seq->prevCellNb = -1;

	fluid_mutex_init(seq->mutex);

	/* start timer */
	if (seq->useSystemTimer) {
		seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process,
					     (void *)seq, TRUE, FALSE, TRUE);
	}
	return (0);
}
Beispiel #6
0
void Chorus::update()
      {
      /* The modulating LFO goes through a full period every x samples: */
      modulation_period_samples = lrint(sample_rate / speed_Hz);

      /* The variation in delay time is x: */
      int modulation_depth_samples = (int)
         (depth_ms / 1000.0  /* convert modulation depth in ms to s*/
         * sample_rate);

      if (modulation_depth_samples > MAX_SAMPLES) {
            fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES);
            modulation_depth_samples = MAX_SAMPLES;
            }

      /* initialize LFO table */
      if (type == FLUID_CHORUS_MOD_SINE)
            sine(lookup_tab, modulation_period_samples, modulation_depth_samples);
      else if (type == FLUID_CHORUS_MOD_TRIANGLE)
            triangle(lookup_tab, modulation_period_samples, modulation_depth_samples);
      else {
            type = FLUID_CHORUS_MOD_SINE;
            sine(lookup_tab, modulation_period_samples, modulation_depth_samples);
            }

      for (int i = 0; i < number_blocks; i++) {
            /* Set the phase of the chorus blocks equally spaced */
            phase[i] = (int) ((double) modulation_period_samples
               * (double) i / (double) number_blocks);
            }

      /* Start of the circular buffer */
      counter = 0;
      }
Beispiel #7
0
/**
 * Create a new sequencer object.
 * @param use_system_timer If TRUE, sequencer will advance at the rate of the
 *   system clock. If FALSE, call fluid_sequencer_process() to advance
 *   the sequencer.
 * @return New sequencer instance
 * @since 1.1.0
 */
fluid_sequencer_t*
new_fluid_sequencer2 (int use_system_timer)
{
	fluid_sequencer_t* seq;

	seq = FLUID_NEW(fluid_sequencer_t);
	if (seq == NULL) {
		fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
		return NULL;
	}

	FLUID_MEMSET(seq, 0, sizeof(fluid_sequencer_t));

	seq->scale = 1000;	// default value
	seq->useSystemTimer = use_system_timer ? TRUE : FALSE;
	seq->startMs = seq->useSystemTimer ? fluid_curtime() : 0;
	seq->clients = NULL;
	seq->clientsID = 0;

	if (-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) {
		FLUID_FREE(seq);
		fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
		return NULL;
	}

#if FLUID_SEQ_WITH_TRACE
	seq->tracelen = 1024*100;
	seq->tracebuf = (char *)FLUID_MALLOC(seq->tracelen);
	if (seq->tracebuf == NULL) {
 		_fluid_seq_queue_end(seq);
 		FLUID_FREE(seq);
		fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
		return NULL;
	}
	seq->traceptr = seq->tracebuf;
#endif

	return(seq);
}
Beispiel #8
0
/**
 * Create a new sequencer event structure.
 * @return New sequencer event structure or NULL if out of memory
 */
fluid_event_t*
new_fluid_event()
{
  fluid_event_t* evt;

  evt = FLUID_NEW(fluid_event_t);
  if (evt == NULL) {
    fluid_log(FLUID_PANIC, "event: Out of memory\n");
    return NULL;
  }
  fluid_event_clear(evt);

  return(evt);
}
Beispiel #9
0
/** 
 * Registers a synthesizer as a destination client of the given sequencer.
 * The \a synth is registered with the name "fluidsynth".
 * @param seq Sequencer instance
 * @param synth Synthesizer instance
 * @returns Sequencer client ID, or #FLUID_FAILED on error.
 */
short 
fluid_sequencer_register_fluidsynth (fluid_sequencer_t* seq, fluid_synth_t* synth)
{
	fluid_seqbind_t* seqbind;
	
	seqbind = FLUID_NEW(fluid_seqbind_t);
	if (seqbind == NULL) {
		fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
		return FLUID_FAILED;
	}

	seqbind->synth = synth;
	seqbind->seq = seq;
	seqbind->sample_timer = NULL;
	seqbind->client_id = -1;

	/* set up the sample timer */
	if (!fluid_sequencer_get_use_system_timer(seq)) {
		seqbind->sample_timer = 
			new_fluid_sample_timer(synth, fluid_seqbind_timer_callback, (void *) seqbind);
		if (seqbind->sample_timer == NULL) {
			fluid_log(FLUID_PANIC, "sequencer: Out of memory\n");
			delete_fluid_seqbind(seqbind);
			return FLUID_FAILED;
		}
	}

	/* register fluidsynth itself */
	seqbind->client_id = 
		fluid_sequencer_register_client(seq, "fluidsynth", fluid_seq_fluidsynth_callback, (void *)seqbind);
	if (seqbind->client_id == -1) {
		delete_fluid_seqbind(seqbind);
		return FLUID_FAILED;
	}

	return seqbind->client_id;
}
Beispiel #10
0
/**
 * Set the time scale of a sequencer.
 * @param seq Sequencer object
 * @param scale Sequencer scale value in ticks per second
 *   (default is 1000 for 1 tick per millisecond, max is 1000.0)
 *
 * If there are already scheduled events in the sequencer and the scale is changed
 * the events are adjusted accordingly.
 */
void
fluid_sequencer_set_time_scale (fluid_sequencer_t* seq, double scale)
{
	if (scale <= 0) {
		fluid_log(FLUID_WARN, "sequencer: scale <= 0 : %f\n", scale);
		return;
	}

	if (scale > 1000.0)
		// Otherwise : problems with the timer = 0ms...
		scale = 1000.0;

	if (seq->scale != scale) {
		double oldScale = seq->scale;

		// stop timer
		if (seq->timer) {
			delete_fluid_timer(seq->timer);
			seq->timer = NULL;
		}

		seq->scale = scale;

		// change start0 so that cellNb is preserved
		seq->queue0StartTime =  (seq->queue0StartTime + seq->prevCellNb)*(seq->scale/oldScale) - seq->prevCellNb;

		// change all preQueue events for new scale
		{
			fluid_evt_entry* tmp;
			tmp = seq->preQueue;
			while (tmp) {
				if (tmp->entryType == FLUID_EVT_ENTRY_INSERT)
					tmp->evt.time = tmp->evt.time*seq->scale/oldScale;

				tmp = tmp->next;
			}
		}

		/* re-start timer */
		if (seq->useSystemTimer) {
			seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process, (void *)seq, TRUE, FALSE, TRUE);
		}
	}
}