예제 #1
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);
}
예제 #2
0
/**
 * Open a MIDI file and return a new MIDI file handle.
 * @internal
 * @param filename Path of file to open.
 * @return New MIDI file handle or NULL on error.
 */
fluid_midi_file* new_fluid_midi_file(char* filename)
{
	fluid_midi_file* mf;

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

	mf->c = -1;
	mf->running_status = -1;
	mf->fp = FLUID_FOPEN(filename, "rb");

	if (mf->fp == NULL) {
		FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
		FLUID_FREE(mf);
		return NULL;
	}

	if (fluid_midi_file_read_mthd(mf) != FLUID_OK) {
		FLUID_FREE(mf);
		return NULL;
	}
	return mf;
}
예제 #3
0
/**
 * new_fluid_hashtable_full:
 * @hash_func: a function to create a hash value from a key.
 * @key_equal_func: a function to check two keys for equality.
 * @key_destroy_func: a function to free the memory allocated for the key
 *   used when removing the entry from the #fluid_hashtable_t or %NULL if you
 *   don't want to supply such a function.
 * @value_destroy_func: a function to free the memory allocated for the
 *   value used when removing the entry from the #fluid_hashtable_t or %NULL if
 *   you don't want to supply such a function.
 *
 * Creates a new #fluid_hashtable_t like fluid_hashtable_new() with a reference count
 * of 1 and allows to specify functions to free the memory allocated for the
 * key and value that get called when removing the entry from the #fluid_hashtable_t.
 *
 * Return value: a new #fluid_hashtable_t.
 **/
fluid_hashtable_t*
new_fluid_hashtable_full (fluid_hash_func_t hash_func,
                          fluid_equal_func_t key_equal_func,
                          fluid_destroy_notify_t key_destroy_func,
                          fluid_destroy_notify_t value_destroy_func)
{
  fluid_hashtable_t *hashtable;

  hashtable = FLUID_NEW (fluid_hashtable_t);

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

  hashtable->size               = HASH_TABLE_MIN_SIZE;
  hashtable->nnodes             = 0;
  hashtable->hash_func          = hash_func ? hash_func : fluid_direct_hash;
  hashtable->key_equal_func     = key_equal_func;
  hashtable->ref_count          = 1;
  hashtable->key_destroy_func   = key_destroy_func;
  hashtable->value_destroy_func = value_destroy_func;
  hashtable->nodes              = FLUID_ARRAY (fluid_hashnode_t*, hashtable->size);
  FLUID_MEMSET (hashtable->nodes, 0, hashtable->size * sizeof (fluid_hashnode_t *));

  return hashtable;
}
예제 #4
0
/*
 * new_fluid_sndmgr_audio_driver
 * This implementation used the 16bit format.
 */
fluid_audio_driver_t*
new_fluid_sndmgr_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
  fluid_sndmgr_audio_driver_t* dev = NULL;
  int period_size, periods, buffer_size;

  /* check the format */
  if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
    FLUID_LOG(FLUID_ERR, "Unhandled sample format");
    return NULL;
  }

  /* 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));

  dev->callback_is_audio_func = false;
  dev->data = (void *)synth;
  dev->callback = NULL;

  if (start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) {
    delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t*)dev);
    return NULL;
  }
  return (fluid_audio_driver_t*)dev;
}
예제 #5
0
/**
 * Create a new MIDI router rule.
 * @return Newly allocated router rule or NULL if out of memory.
 * @since 1.1.0
 *
 * The new rule is a "unity" rule which will accept any values and wont modify
 * them.
 */
fluid_midi_router_rule_t *
new_fluid_midi_router_rule (void)
{
  fluid_midi_router_rule_t *rule;

  rule = FLUID_NEW (fluid_midi_router_rule_t);

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

  FLUID_MEMSET (rule, 0, sizeof (fluid_midi_router_rule_t));

  rule->chan_min = 0;
  rule->chan_max = 999999;
  rule->chan_mul = 1.0;
  rule->chan_add = 0;
  rule->par1_min = 0;
  rule->par1_max = 999999;
  rule->par1_mul = 1.0;
  rule->par1_add = 0;
  rule->par2_min = 0;
  rule->par2_max = 999999;
  rule->par2_mul = 1.0;
  rule->par2_add = 0;

  return rule;
};
예제 #6
0
/**
 * Return a new MIDI file handle for parsing an already-loaded MIDI file.
 * @internal
 * @param buffer Pointer to full contents of MIDI file (borrows the pointer).
 *  The caller must not free buffer until after the fluid_midi_file is deleted.
 * @param length Size of the buffer in bytes.
 * @return New MIDI file handle or NULL on error.
 */
fluid_midi_file *
new_fluid_midi_file(const char* buffer, size_t length)
{
    fluid_midi_file *mf;

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

    mf->c = -1;
    mf->running_status = -1;

    mf->buffer = buffer;
    mf->buf_len = length;
    mf->buf_pos = 0;
    mf->eof = FALSE;

    if (fluid_midi_file_read_mthd(mf) != FLUID_OK) {
        FLUID_FREE(mf);
        return NULL;
    }
    return mf;
}
예제 #7
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);
}
예제 #8
0
fluid_midi_driver_t *
new_fluid_sndio_midi_driver(fluid_settings_t *settings,
			       handle_midi_event_func_t handler, void *data)
{
  int err;
  fluid_sndio_midi_driver_t *dev;
  char *device;

  /* not much use doing anything */
  if (handler == NULL) {
    FLUID_LOG(FLUID_ERR, "Invalid argument");
    return NULL;
  }

  /* allocate the device */
  dev = FLUID_NEW(fluid_sndio_midi_driver_t);
  if (dev == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }
  FLUID_MEMSET(dev, 0, sizeof(fluid_sndio_midi_driver_t));
  dev->hdl = NULL;

  dev->driver.handler = handler;
  dev->driver.data = data;

  /* allocate one event to store the input data */
  dev->parser = new_fluid_midi_parser();
  if (dev->parser == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    goto error_recovery;
  }

  /* get the device name. if none is specified, use the default device. */
  if (!fluid_settings_dupstr(settings, "midi.sndio.device", &device)) {
	device = NULL;
  }

  /* open the default hardware device. only use midi in. */
  dev->hdl = mio_open(device, MIO_IN, 0);
  if (dev->hdl == NULL) {
    FLUID_LOG(FLUID_ERR, "Couldn't open sndio midi device");
    goto error_recovery;
  }

  dev->status = FLUID_MIDI_READY;

  err = pthread_create(&dev->thread, NULL, fluid_sndio_midi_run, (void *)dev);
  if (err) {
    FLUID_LOG(FLUID_PANIC, "Couldn't create the midi thread.");
    goto error_recovery;
  }
  return (fluid_midi_driver_t *) dev;

 error_recovery:
  delete_fluid_sndio_midi_driver((fluid_midi_driver_t *)dev);
  return NULL;
}
예제 #9
0
void
fluid_event_clear(fluid_event_t* evt)
{
  FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));

  // by default, no type
  evt->dest = -1;
  evt->src = -1;
  evt->type = -1;
}
예제 #10
0
fluid_server_socket_t*
new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
{
  fluid_server_socket_t* server_socket;
  struct sockaddr_in addr;
  fluid_socket_t sock;

  g_return_val_if_fail (func != NULL, NULL);

  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock == INVALID_SOCKET) {
    FLUID_LOG(FLUID_ERR, "Failed to create server socket");
    return NULL;
  }

  FLUID_MEMSET((char *)&addr, 0, sizeof(struct sockaddr_in));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  addr.sin_port = htons(port);

  if (bind(sock, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
    FLUID_LOG(FLUID_ERR, "Failed to bind server socket");
    fluid_socket_close(sock);
    return NULL;
  }

  if (listen(sock, 10) == SOCKET_ERROR) {
    FLUID_LOG(FLUID_ERR, "Failed listen on server socket");
    fluid_socket_close(sock);
    return NULL;
  }

  server_socket = FLUID_NEW(fluid_server_socket_t);
  if (server_socket == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    fluid_socket_close(sock);
    return NULL;
  }

  server_socket->socket = sock;
  server_socket->func = func;
  server_socket->data = data;
  server_socket->cont = 1;

  server_socket->thread = new_fluid_thread(fluid_server_socket_run, server_socket,
                                           0, FALSE);
  if (server_socket->thread == NULL) {
    FLUID_FREE(server_socket);
    fluid_socket_close(sock);
    return NULL;
  }

  return server_socket;
}
예제 #11
0
/* Private functions */
static fluid_samplecache_entry_t *new_samplecache_entry(SFData *sf,
                                                        unsigned int sample_start,
                                                        unsigned int sample_end,
                                                        int sample_type)
{
    fluid_samplecache_entry_t *entry;

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

    entry->filename = FLUID_STRDUP(sf->fname);
    if (entry->filename == NULL)
    {
        FLUID_LOG(FLUID_ERR, "Out of memory");
        goto error_exit;
    }

    if (fluid_get_file_modification_time(entry->filename, &entry->modification_time) == FLUID_FAILED)
    {
        FLUID_LOG(FLUID_WARN, "Unable to read modificaton time of soundfont file.");
        entry->modification_time = 0;
    }

    entry->sf_samplepos = sf->samplepos;
    entry->sf_samplesize = sf->samplesize;
    entry->sf_sample24pos = sf->sample24pos;
    entry->sf_sample24size = sf->sample24size;
    entry->sample_start = sample_start;
    entry->sample_end = sample_end;
    entry->sample_type = sample_type;

    entry->sample_count = fluid_sffile_read_sample_data(sf, sample_start, sample_end, sample_type,
            &entry->sample_data, &entry->sample_data24);
    if (entry->sample_count < 0)
    {
        goto error_exit;
    }

    return entry;

error_exit:
    delete_samplecache_entry(entry);
    return NULL;
}
예제 #12
0
static LONG APIENTRY fluid_dart_audio_run( ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags )
{
    fluid_dart_audio_driver_t* dev=(fluid_dart_audio_driver_t*)pBuffer->ulUserParm;

    switch( ulFlags ) {
        case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE: /* error occur in device */
        case MIX_WRITE_COMPLETE:                    /* for playback  */
            FLUID_MEMSET(pBuffer->pBuffer, 0, pBuffer->ulBufferLength);
            fluid_synth_write_s16(dev->synth, pBuffer->ulBufferLength / dev->frame_size,
                                  pBuffer->pBuffer, 0, 2, pBuffer->pBuffer, 1, 2 );
            dev->MixSetupParms.pmixWrite(dev->MixSetupParms.ulMixHandle, pBuffer, 1);
            break;
    }

    return TRUE;
}
예제 #13
0
static void
fluid_server_socket_run (void *data)
{
  fluid_server_socket_t *server_socket = (fluid_server_socket_t *)data;
  fluid_socket_t client_socket;
#ifdef IPV6
  struct sockaddr_in6 addr;
  char straddr[INET6_ADDRSTRLEN];
#else
  struct sockaddr_in addr;
  char straddr[INET_ADDRSTRLEN];
#endif
  socklen_t addrlen = sizeof (addr);
  int retval;
  FLUID_MEMSET((char *)&addr, 0, sizeof(addr));

  FLUID_LOG (FLUID_DBG, "Server listening for connections");

  while (server_socket->cont)
  {
    client_socket = accept (server_socket->socket, (struct sockaddr *)&addr, &addrlen);

    FLUID_LOG (FLUID_DBG, "New client connection");

    if (client_socket == INVALID_SOCKET)
    {
      if (server_socket->cont)
	FLUID_LOG(FLUID_ERR, "Failed to accept connection");

      server_socket->cont = 0;
      return;
    } else {
#ifdef IPV6
      inet_ntop(AF_INET6, &addr.sin6_addr, straddr, sizeof(straddr));
#else
      inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr));
#endif
      retval = server_socket->func (server_socket->data, client_socket,
                                    straddr);

      if (retval != 0)
	fluid_socket_close(client_socket);
    }
  }

  FLUID_LOG(FLUID_DBG, "Server closing");
}
예제 #14
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;
}
예제 #15
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);
}
예제 #16
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;
}
예제 #17
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;
}
예제 #18
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;
}
예제 #19
0
/*
 * new_fluid_dsound_audio_driver
 */
fluid_audio_driver_t*
new_fluid_dsound_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
  HRESULT hr;
  DSBUFFERDESC desc;
  fluid_dsound_audio_driver_t* dev = NULL;
  DSCAPS caps;
  char *buf1;
  DWORD bytes1;
  double sample_rate;
  int periods, period_size;
  fluid_dsound_devsel_t devsel;

  /* check if the globals are initialized */
  if (FLUID_HINSTANCE == NULL) {
    FLUID_LOG(FLUID_ERR, "FluidSynth hinstance not set, which is needed for DirectSound");
    return NULL;
  }

/*
  if (fluid_wnd == NULL) {
    if (fluid_win32_create_window() != 0) {
      FLUID_LOG(FLUID_ERR, "Couldn't create window needed for DirectSound");
      return NULL;
    }
  }
*/
  /* create and clear the driver data */
  dev = FLUID_NEW(fluid_dsound_audio_driver_t);
  if (dev == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }
  FLUID_MEMSET(dev, 0, sizeof(fluid_dsound_audio_driver_t));

  dev->synth = synth;
  dev->cont = 1;

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

  /* check the format */
  if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
    FLUID_LOG(FLUID_ERR, "Unhandled sample format");
    goto error_recovery;
  }

  dev->frame_size = 2 * sizeof(short);
  dev->buffer_byte_size = period_size * dev->frame_size;
  dev->queue_byte_size = periods * dev->buffer_byte_size;
  dev->write = fluid_synth_write_s16;

  /* create and initialize the buffer format */
  dev->format = (WAVEFORMATEX*) FLUID_MALLOC(sizeof(WAVEFORMATEX));
  if (dev->format == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    goto error_recovery;
  }
  ZeroMemory(dev->format, sizeof(WAVEFORMATEX));

  dev->format->wFormatTag = WAVE_FORMAT_PCM;
  dev->format->nChannels = 2;
  dev->format->wBitsPerSample = 16;
  dev->format->nSamplesPerSec = (DWORD) sample_rate;
  dev->format->nBlockAlign = (WORD) dev->frame_size;
  dev->format->nAvgBytesPerSec = dev->format->nSamplesPerSec * dev->frame_size;
  dev->format->cbSize = 0;

  devsel.devGUID = NULL;
  /* get the selected device name. if none is specified, use NULL for the default device. */
  if(fluid_settings_dupstr(settings, "audio.dsound.device", &devsel.devname) == FLUID_OK /* ++ alloc device name */
     && devsel.devname && strlen (devsel.devname) > 0) {
    /* look for the GUID of the selected device */
    DirectSoundEnumerate((LPDSENUMCALLBACK) fluid_dsound_enum_callback2, (void *)&devsel);
  }

  if (devsel.devname) FLUID_FREE (devsel.devname);      /* -- free device name */

  /* open DirectSound */
  hr = DirectSoundCreate(devsel.devGUID, &dev->direct_sound, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to create the DirectSound object");
    goto error_recovery;
  }

  hr = IDirectSound_SetCooperativeLevel(dev->direct_sound, fluid_win32_get_window(), DSSCL_PRIORITY);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to set the cooperative level");
    goto error_recovery;
  }

  caps.dwSize = sizeof(caps);
  hr = IDirectSound_GetCaps(dev->direct_sound, &caps);
  if (hr != DS_OK)  {
    FLUID_LOG(FLUID_ERR, "Failed to query the device capacities");
    goto error_recovery;
  }

  /* create primary buffer */

  ZeroMemory(&desc, sizeof(DSBUFFERDESC));
  desc.dwSize = sizeof(DSBUFFERDESC);
  desc.dwFlags = DSBCAPS_PRIMARYBUFFER;

  if (caps.dwFreeHwMixingStreamingBuffers > 0) {
    desc.dwFlags |= DSBCAPS_LOCHARDWARE;
  }

  hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->prim_buffer, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to allocate the primary buffer");
    goto error_recovery;
  }

  /* set the primary sound buffer to this format. if it fails, just
     print a warning. */
  hr = IDirectSoundBuffer_SetFormat(dev->prim_buffer, dev->format);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_WARN, "Can't set format of primary sound buffer", fluid_win32_error(hr));
  }

  /* initialize the buffer description */

  ZeroMemory(&desc, sizeof(DSBUFFERDESC));
  desc.dwSize = sizeof(DSBUFFERDESC);
  desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
  desc.lpwfxFormat = dev->format;
  desc.dwBufferBytes = dev->queue_byte_size;
  desc.dwReserved = 0;

  if (caps.dwFreeHwMixingStreamingBuffers > 0) {
    desc.dwFlags |= DSBCAPS_LOCHARDWARE;
  }

  /* create the secondary sound buffer */

  hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->sec_buffer, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "dsound: Can't create sound buffer: %s", fluid_win32_error(hr));
    goto error_recovery;
  }


  /* Lock */
  hr = IDirectSoundBuffer_Lock(dev->sec_buffer, 0, 0, (void*) &buf1, &bytes1, 0, 0, DSBLOCK_ENTIREBUFFER);

  if ((hr != DS_OK) || (buf1 == NULL)) {
    FLUID_LOG(FLUID_PANIC, "Failed to lock the audio buffer. Exiting.");
    goto error_recovery;
  }

  /* fill the buffer with silence */
  memset(buf1, 0, bytes1);

  /* Unlock */
  IDirectSoundBuffer_Unlock(dev->sec_buffer, buf1, bytes1, 0, 0);


  /* start the audio thread */
  dev->thread = CreateThread(NULL, 0, &fluid_dsound_audio_run, (LPVOID) dev, 0, &dev->threadID);
  if (dev->thread == NULL) {
    goto error_recovery;
  }

  return (fluid_audio_driver_t*) dev;

 error_recovery:
  delete_fluid_dsound_audio_driver((fluid_audio_driver_t*) dev);
  return NULL;
}
/*
 * new_fluid_core_audio_driver2
 */
fluid_audio_driver_t*
new_fluid_core_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
{
  char* devname = NULL;
  fluid_core_audio_driver_t* dev = NULL;
  int period_size, periods;
  double sample_rate;
  OSStatus status;
  UInt32 size;
  int i;

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

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

  // Open the default output unit
  ComponentDescription desc;
  desc.componentType = kAudioUnitType_Output;
  desc.componentSubType = kAudioUnitSubType_HALOutput; //kAudioUnitSubType_DefaultOutput;
  desc.componentManufacturer = kAudioUnitManufacturer_Apple;
  desc.componentFlags = 0;
  desc.componentFlagsMask = 0;

  Component comp = FindNextComponent(NULL, &desc);
  if (comp == NULL) {
    FLUID_LOG(FLUID_ERR, "Failed to get the default audio device");
    goto error_recovery;
  }

  status = OpenAComponent(comp, &dev->outputUnit);
  if (status != noErr) {
    FLUID_LOG(FLUID_ERR, "Failed to open the default audio device. Status=%ld\n", (long int)status);
    goto error_recovery;
  }

  // Set up a callback function to generate output
  AURenderCallbackStruct render;
  render.inputProc = fluid_core_audio_callback;
  render.inputProcRefCon = (void *) dev;
  status = AudioUnitSetProperty (dev->outputUnit,
                                 kAudioUnitProperty_SetRenderCallback,
                                 kAudioUnitScope_Input,
                                 0,
                                 &render,
                                 sizeof(render));
  if (status != noErr) {
    FLUID_LOG (FLUID_ERR, "Error setting the audio callback. Status=%ld\n", (long int)status);
    goto error_recovery;
  }

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

  /* get the selected device name. if none is specified, use NULL for the default device. */
  if (fluid_settings_dupstr(settings, "audio.coreaudio.device", &devname)  /* alloc device name */
      && devname && strlen (devname) > 0) {
    AudioObjectPropertyAddress pa;
    pa.mSelector = kAudioHardwarePropertyDevices;
    pa.mScope = kAudioObjectPropertyScopeWildcard;
    pa.mElement = kAudioObjectPropertyElementMaster;
    if (OK (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, 0, &size))) {
      int num = size / (int) sizeof (AudioDeviceID);
      AudioDeviceID devs [num];
      if (OK (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, devs))) {
        for (i = 0; i < num; ++i) {
          char name [1024];
          size = sizeof (name);
          pa.mSelector = kAudioDevicePropertyDeviceName;
          if (OK (AudioObjectGetPropertyData (devs[i], &pa, 0, 0, &size, name))) {
            if (get_num_outputs (devs[i]) > 0 && strcasecmp(devname, name) == 0) {
              AudioDeviceID selectedID = devs[i];
              status = AudioUnitSetProperty (dev->outputUnit,
                                             kAudioOutputUnitProperty_CurrentDevice,
                                             kAudioUnitScope_Global,
                                             0,
                                             &selectedID,
                                             sizeof(AudioDeviceID));
              if (status != noErr) {
                FLUID_LOG (FLUID_ERR, "Error setting the selected output device. Status=%ld\n", (long int)status);
                goto error_recovery;
              }
            }
          }
        }
      }
    }
  }

  if (devname)
    FLUID_FREE (devname); /* free device name */

  dev->buffer_size = period_size * periods;

  // The DefaultOutputUnit should do any format conversions
  // necessary from our format to the device's format.
  dev->format.mSampleRate = sample_rate; // sample rate of the audio stream
  dev->format.mFormatID = kAudioFormatLinearPCM; // encoding type of the audio stream
  dev->format.mFormatFlags = kLinearPCMFormatFlagIsFloat;
  dev->format.mBytesPerPacket = 2*sizeof(float);
  dev->format.mFramesPerPacket = 1;
  dev->format.mBytesPerFrame = 2*sizeof(float);
  dev->format.mChannelsPerFrame = 2;
  dev->format.mBitsPerChannel = 8*sizeof(float);

  FLUID_LOG (FLUID_DBG, "mSampleRate %g", dev->format.mSampleRate);
  FLUID_LOG (FLUID_DBG, "mFormatFlags %08X", dev->format.mFormatFlags);
  FLUID_LOG (FLUID_DBG, "mBytesPerPacket %d", dev->format.mBytesPerPacket);
  FLUID_LOG (FLUID_DBG, "mFramesPerPacket %d", dev->format.mFramesPerPacket);
  FLUID_LOG (FLUID_DBG, "mChannelsPerFrame %d", dev->format.mChannelsPerFrame);
  FLUID_LOG (FLUID_DBG, "mBytesPerFrame %d", dev->format.mBytesPerFrame);
  FLUID_LOG (FLUID_DBG, "mBitsPerChannel %d", dev->format.mBitsPerChannel);

  status = AudioUnitSetProperty (dev->outputUnit,
                                 kAudioUnitProperty_StreamFormat,
                                 kAudioUnitScope_Input,
                                 0,
                                 &dev->format,
                                 sizeof(AudioStreamBasicDescription));
  if (status != noErr) {
    FLUID_LOG (FLUID_ERR, "Error setting the audio format. Status=%ld\n", (long int)status);
    goto error_recovery;
  }

  status = AudioUnitSetProperty (dev->outputUnit,
                                 kAudioUnitProperty_MaximumFramesPerSlice,
                                 kAudioUnitScope_Input,
                                 0,
                                 &dev->buffer_size,
                                 sizeof(unsigned int));
  if (status != noErr) {
    FLUID_LOG (FLUID_ERR, "Failed to set the MaximumFramesPerSlice. Status=%ld\n", (long int)status);
    goto error_recovery;
  }
  FLUID_LOG (FLUID_DBG, "MaximumFramesPerSlice = %d", dev->buffer_size);

  dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size);
  dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size);

  // Initialize the audio unit
  status = AudioUnitInitialize(dev->outputUnit);
  if (status != noErr) {
    FLUID_LOG (FLUID_ERR, "Error calling AudioUnitInitialize(). Status=%ld\n", (long int)status);
    goto error_recovery;
  }

  // Start the rendering
  status = AudioOutputUnitStart (dev->outputUnit);
  if (status != noErr) {
    FLUID_LOG (FLUID_ERR, "Error calling AudioOutputUnitStart(). Status=%ld\n", (long int)status);
    goto error_recovery;
  }

  return (fluid_audio_driver_t*) dev;

error_recovery:

  delete_fluid_core_audio_driver((fluid_audio_driver_t*) dev);
  return NULL;
}
예제 #21
0
/*
 * new_fluid_midishare_midi_driver
 */
fluid_midi_driver_t*
new_fluid_midishare_midi_driver(fluid_settings_t* settings,
                                handle_midi_event_func_t handler,
                                void* data)
{
    fluid_midishare_midi_driver_t* dev;
    int i;

    /* not much use doing anything */
    if (handler == NULL) {
        FLUID_LOG(FLUID_ERR, "Invalid argument");
        return NULL;
    }

    /* allocate the device */
    dev = FLUID_NEW(fluid_midishare_midi_driver_t);
    if (dev == NULL) {
        FLUID_LOG(FLUID_ERR, "Out of memory");
        return NULL;
    }
    FLUID_MEMSET(dev, 0, sizeof(fluid_midishare_midi_driver_t));
    dev->driver.handler = handler;
    dev->driver.data = data;

    /* register to MidiShare as Application or Driver */
#if defined(MIDISHARE_DRIVER)
    if (!fluid_midishare_open_driver(dev)) goto error_recovery;
#else
    if (!fluid_midishare_open_appl(dev)) goto error_recovery;
#endif

    /*MidiSetInfo(dev->refnum, dev->router->synth); */
    MidiSetInfo(dev->refnum, dev);
    dev->filter = MidiNewFilter();
    if (dev->filter == 0) {
        FLUID_LOG(FLUID_ERR, "Can not allocate MidiShare filter");
        goto error_recovery;
    }

    for (i = 0 ; i < 256; i++) {
        MidiAcceptPort(dev->filter, i, 1); /* accept all ports */
        MidiAcceptType(dev->filter, i, 0); /* reject all types */
    }

    for (i = 0 ; i < 16; i++) {
        MidiAcceptChan(dev->filter, i, 1); /* accept all chan */
    }

    /* accept only the following types */
    MidiAcceptType(dev->filter, typeNote, 1);
    MidiAcceptType(dev->filter, typeKeyOn, 1);
    MidiAcceptType(dev->filter, typeKeyOff, 1);
    MidiAcceptType(dev->filter, typeCtrlChange, 1);
    MidiAcceptType(dev->filter, typeProgChange, 1);
    MidiAcceptType(dev->filter, typePitchWheel, 1);
    MidiAcceptType(dev->filter, typeSysEx, 1);

    /* set the filter */
    MidiSetFilter(dev->refnum, dev->filter);

    dev->status = FLUID_MIDI_READY;
    return (fluid_midi_driver_t*) dev;

error_recovery:
    delete_fluid_midishare_midi_driver((fluid_midi_driver_t*) dev);
    return NULL;
}
예제 #22
0
fluid_audio_driver_t *
new_fluid_portaudio_driver (fluid_settings_t *settings, fluid_synth_t *synth)
{
  fluid_portaudio_driver_t *dev = NULL;
  PaStreamParameters outputParams;
  char *device = NULL;
  double sample_rate;
  int period_size;
  PaError err;

  dev = FLUID_NEW (fluid_portaudio_driver_t);

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

  err = Pa_Initialize ();

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

  FLUID_MEMSET (dev, 0, sizeof (fluid_portaudio_driver_t));

  dev->synth = synth;

  fluid_settings_getint (settings, "audio.period-size", &period_size);
  fluid_settings_getnum (settings, "synth.sample-rate", &sample_rate);
  fluid_settings_dupstr(settings, "audio.portaudio.device", &device);   /* ++ alloc device name */

  bzero (&outputParams, sizeof (outputParams));
  outputParams.channelCount = 2;
  outputParams.suggestedLatency = (PaTime)period_size / sample_rate;

  /* Locate the device if specified */
  if (strcmp (device, PORTAUDIO_DEFAULT_DEVICE) != 0)
  {
    const PaDeviceInfo *deviceInfo;
    int numDevices;
    int i;

    numDevices = Pa_GetDeviceCount ();

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

    for (i = 0; i < numDevices; i++)
    {
      deviceInfo = Pa_GetDeviceInfo (i);

      if (strcmp (device, deviceInfo->name) == 0)
      {
        outputParams.device = i;
        break;
      }
    }

    if (i == numDevices)
    {
      FLUID_LOG (FLUID_ERR, "PortAudio device '%s' was not found", device);
      goto error_recovery;
    }
  }
  else outputParams.device = Pa_GetDefaultOutputDevice();

  if (fluid_settings_str_equal (settings, "audio.sample-format", "16bits"))
  {
    outputParams.sampleFormat = paInt16;
    dev->read = fluid_synth_write_s16;
  }
  else if (fluid_settings_str_equal (settings, "audio.sample-format", "float"))
  {
    outputParams.sampleFormat = paFloat32;
    dev->read = fluid_synth_write_float;
  }
  else
  {
    FLUID_LOG (FLUID_ERR, "Unknown sample format");
    goto error_recovery;
  }

  /* PortAudio section */

  /* Open an audio I/O stream. */
  err = Pa_OpenStream (&dev->stream,
                       NULL,              /* Input parameters */
                       &outputParams,
                       sample_rate,
                       period_size,
                       paNoFlag,
                       fluid_portaudio_run,
                       dev);

  if (err != paNoError)
  {
    FLUID_LOG (FLUID_ERR, "Error opening PortAudio stream: %s",
               Pa_GetErrorText (err));
    goto error_recovery;
  }

  err = Pa_StartStream (dev->stream);

  if (err != paNoError)
  {
    FLUID_LOG (FLUID_ERR, "Error starting PortAudio stream: %s",
               Pa_GetErrorText (err));
    goto error_recovery;
  }

  if (device) FLUID_FREE (device);      /* -- free device name */
  
  return (fluid_audio_driver_t *)dev;

error_recovery:
  if (device) FLUID_FREE (device);      /* -- free device name */
  delete_fluid_portaudio_driver ((fluid_audio_driver_t *)dev);
  return NULL;
}
예제 #23
0
fluid_audio_driver_t*
new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
    fluid_dart_audio_driver_t* dev;
    double sample_rate;
    int periods, period_size;
    UCHAR szFailedName[ 256 ];
    MCI_AMP_OPEN_PARMS AmpOpenParms;
    int i;
    ULONG rc;

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

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

    /* check the format */
    if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
        FLUID_LOG(FLUID_ERR, "Unhandled sample format");
        goto error_recovery;
    }

    dev->synth = synth;
    dev->frame_size = 2 * sizeof(short);

    /* Load only once
     */
    if( m_hmodMDM == NULLHANDLE )
    {
        rc = DosLoadModule(szFailedName, sizeof(szFailedName), "MDM", &m_hmodMDM);

        if (rc != 0 ) {
            FLUID_LOG(FLUID_ERR, "Cannot load MDM.DLL for DART due to %s", szFailedName);
            goto error_recovery;
        }

        rc = DosQueryProcAddr(m_hmodMDM, 1, NULL, (PFN *)&m_pfnmciSendCommand);

        if (rc != 0 ) {
            FLUID_LOG(FLUID_ERR, "Cannot find mciSendCommand() in MDM.DLL");
            DosFreeModule(m_hmodMDM);
            m_hmodMDM = NULLHANDLE;
            goto error_recovery;
        }
    }

    /* open the mixer device
     */
    FLUID_MEMSET(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
    AmpOpenParms.usDeviceID = (USHORT)0;
    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;

    rc = m_pfnmciSendCommand(0, MCI_OPEN,
                             MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
                             (PVOID)&AmpOpenParms, 0);

    if (rc != MCIERR_SUCCESS) {
        FLUID_LOG(FLUID_ERR, "Cannot open DART, rc = %lu", rc);
        goto error_recovery;
    }

    dev->usDeviceID = AmpOpenParms.usDeviceID;

    /* Set the MixSetupParms data structure to match the requirements.
     * This is a global that is used to setup the mixer.
     */
    dev->MixSetupParms.ulBitsPerSample = BPS_16;
    dev->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
    dev->MixSetupParms.ulSamplesPerSec = sample_rate;
    dev->MixSetupParms.ulChannels = 2;

    /* Setup the mixer for playback of wave data
     */
    dev->MixSetupParms.ulFormatMode = MCI_PLAY;
    dev->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
    dev->MixSetupParms.pmixEvent    = fluid_dart_audio_run;

    rc = m_pfnmciSendCommand(dev->usDeviceID, MCI_MIXSETUP,
                             MCI_WAIT | MCI_MIXSETUP_INIT,
                             (PVOID)&dev->MixSetupParms, 0);

    if (rc != MCIERR_SUCCESS) {
        FLUID_LOG(FLUID_ERR, "Cannot setup DART, rc = %lu", rc);
        goto error_recovery;
    }

    /* Set up the BufferParms data structure and allocate
     * device buffers from the Amp-Mixer
     */
    dev->BufferParms.ulNumBuffers = NUM_MIX_BUFS;
    dev->BufferParms.ulBufferSize = periods * period_size * dev->frame_size;
    dev->BufferParms.pBufList = dev->MixBuffers;

    rc = m_pfnmciSendCommand(dev->usDeviceID, MCI_BUFFER,
                             MCI_WAIT | MCI_ALLOCATE_MEMORY,
                             (PVOID)&dev->BufferParms, 0);

    if ((USHORT)rc != MCIERR_SUCCESS) {
        FLUID_LOG(FLUID_ERR, "Cannot allocate memory for DART, rc = %lu", rc);
        goto error_recovery;
    }

    /* Initialize all device buffers.
     */
    for (i = 0; i < NUM_MIX_BUFS; i++) {
       FLUID_MEMSET(dev->MixBuffers[i].pBuffer, 0, dev->BufferParms.ulBufferSize);
       dev->MixBuffers[i].ulBufferLength = dev->BufferParms.ulBufferSize;
       dev->MixBuffers[i].ulFlags = 0;
       dev->MixBuffers[i].ulUserParm = (ULONG)dev;
       fluid_synth_write_s16(dev->synth, dev->MixBuffers[i].ulBufferLength / dev->frame_size,
                             dev->MixBuffers[i].pBuffer, 0, 2, dev->MixBuffers[i].pBuffer, 1, 2 );
    }

    /* Write buffers to kick off the amp mixer.
     */
    dev->MixSetupParms.pmixWrite(dev->MixSetupParms.ulMixHandle,
                                 dev->MixBuffers,
                                 NUM_MIX_BUFS);

    return (fluid_audio_driver_t*) dev;

error_recovery:

    delete_fluid_dart_audio_driver((fluid_audio_driver_t*) dev);
    return NULL;
}
예제 #24
0
fluid_audio_driver_t *
new_fluid_portaudio_driver2 (fluid_settings_t *settings, fluid_audio_func_t func, void* data)
{
  fluid_portaudio_driver_t *dev = NULL;
  PaStreamParameters outputParams;
  char *device = NULL;
  double sample_rate;
  int period_size;
  PaError err;
  int numOutputs = 2;

  dev = FLUID_NEW (fluid_portaudio_driver_t);

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

  err = Pa_Initialize ();

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

  FLUID_MEMSET (dev, 0, sizeof (fluid_portaudio_driver_t));
  dev->data = data;
  dev->callback = func;

  bzero (&outputParams, sizeof (outputParams));

  fluid_settings_getint (settings, "audio.period-size", &period_size);
  fluid_settings_getnum (settings, "synth.sample-rate", &sample_rate);
  fluid_settings_dupstr(settings, "audio.portaudio.device", &device);   /* ++ alloc device name */

  /* Locate the device if specified */

  if (strcmp (device, PORTAUDIO_DEFAULT_DEVICE) != 0)
  {
    const PaDeviceInfo *deviceInfo;
    int numDevices;
    int i;

    numDevices = Pa_GetDeviceCount ();

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

    for (i = 0; i < numDevices; i++)
    {
      deviceInfo = Pa_GetDeviceInfo (i);

      if (strcmp (device, deviceInfo->name) == 0)
      {
        outputParams.device = i;
		numOutputs = deviceInfo->maxOutputChannels;
        break;
      }
    }

    if (i == numDevices)
    {
      FLUID_LOG (FLUID_ERR, "PortAudio device '%s' was not found", device);
      goto error_recovery;
    }
  }
  else outputParams.device = Pa_GetDefaultOutputDevice();

  fluid_settings_getint(settings, "audio.portaudio.channelL", &(dev->chanL));
  fluid_settings_getint(settings, "audio.portaudio.channelR", &(dev->chanR));
  dev->chansOpen = 1 + ((dev->chanL > dev->chanR) ? dev->chanL : dev->chanR);
  if (dev->chansOpen > numOutputs) {
    // error
    FLUID_LOG (FLUID_ERR, "One specified channel is greater than the maximum number of channels: L=%d, R=%d, max=%d\n", dev->chanL, dev->chanR, numOutputs-1);
    goto error_recovery;
  }
  dev->buffer_size = period_size;
  dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size);
  dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size);

  outputParams.channelCount = dev->chansOpen;
  outputParams.suggestedLatency = (PaTime)period_size / sample_rate;

  // force float format
  outputParams.sampleFormat = paFloat32;

  /* PortAudio section */

  /* Open an audio I/O stream. */
  err = Pa_OpenStream (&dev->stream,
                       NULL,              /* Input parameters */
                       &outputParams,
                       sample_rate,
                       period_size,
                       paNoFlag,
                       fluid_portaudio_run,
                       dev);

  if (err != paNoError)
  {
    FLUID_LOG (FLUID_ERR, "Error opening PortAudio stream: %s",
               Pa_GetErrorText (err));
    goto error_recovery;
  }

  err = Pa_StartStream (dev->stream);

  if (err != paNoError)
  {
    FLUID_LOG (FLUID_ERR, "Error starting PortAudio stream: %s",
               Pa_GetErrorText (err));
    goto error_recovery;
  }

  if (device) FLUID_FREE (device);      /* -- free device name */
  
  return (fluid_audio_driver_t *)dev;

error_recovery:
  if (device) FLUID_FREE (device);      /* -- free device name */
  delete_fluid_portaudio_driver ((fluid_audio_driver_t *)dev);
  return NULL;
}
예제 #25
0
/*
 * new_fluid_sndio_audio_driver
 */
fluid_audio_driver_t*
new_fluid_sndio_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
  fluid_sndio_audio_driver_t* dev = NULL;
  double sample_rate;
  int periods, period_size;
  char* devname;
  pthread_attr_t attr;
  int err;

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

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

  dev->hdl = NULL;
  dev->synth = synth;
  dev->callback = NULL;
  dev->data = NULL;
  dev->cont = 1;

  if (!fluid_settings_dupstr(settings, "audio.sndio.device", &devname)) {
    devname = NULL;
  }

  dev->hdl = sio_open(devname, SIO_PLAY, 0);
  if (dev->hdl == NULL) {
    FLUID_LOG(FLUID_ERR, "sndio could not be opened for writing");
    goto error_recovery;
  }

  sio_initpar(&dev->par);

  if (fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
    dev->par.bits = 16;
    dev->par.le = SIO_LE_NATIVE;
    dev->read = fluid_synth_write_s16;
  } else {
    FLUID_LOG(FLUID_ERR, "Unknown sample format");
    goto error_recovery;
  }

  dev->par.appbufsz = period_size * periods;
  dev->par.round = period_size;

  dev->par.pchan = 2;
  dev->par.rate = sample_rate;

  if (!sio_setpar(dev->hdl, &dev->par)) {
    FLUID_LOG(FLUID_ERR, "Couldn't set sndio audio parameters");
    goto error_recovery;
  }

  if (!sio_getpar(dev->hdl, &dev->par)) {
    FLUID_LOG(FLUID_ERR, "Couldn't get sndio audio parameters");
    goto error_recovery;
  } else if (dev->par.pchan != 2 || dev->par.rate != sample_rate ||
      dev->par.bits != 16) {
    FLUID_LOG(FLUID_ERR, "Couldn't set sndio audio parameters as desired");
    goto error_recovery;
  }

  dev->buffer_size = dev->par.round;
  dev->buffer_byte_size = dev->par.round * dev->par.bps * dev->par.pchan;

  dev->buffer = FLUID_MALLOC(dev->buffer_byte_size);
  if (dev->buffer == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    goto error_recovery;
  }

  if (!sio_start(dev->hdl)) {
    FLUID_LOG(FLUID_ERR, "Couldn't start sndio");
    goto error_recovery;
  }

  if (pthread_attr_init(&attr)) {
    FLUID_LOG(FLUID_ERR, "Couldn't initialize audio thread attributes");
    goto error_recovery;
  }

  err = pthread_create(&dev->thread, &attr, fluid_sndio_audio_run, (void*) dev);
  if (err) {
    FLUID_LOG(FLUID_ERR, "Couldn't create audio thread");
    goto error_recovery;
  }

  return (fluid_audio_driver_t*) dev;

error_recovery:
  delete_fluid_sndio_audio_driver((fluid_audio_driver_t*) dev);
  return NULL;
}
예제 #26
0
fluid_audio_driver_t*
new_fluid_sndio_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
{
  fluid_sndio_audio_driver_t* dev = NULL;
  double sample_rate;
  int periods, period_size;
  char* devname;
  pthread_attr_t attr;
  int err;

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

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

  dev->hdl = NULL;
  dev->synth = NULL;
  dev->read = NULL;
  dev->callback = func;
  dev->data = data;
  dev->cont = 1;

  if (!fluid_settings_dupstr(settings, "audio.sndio.device", &devname)) {
    devname = NULL;
  }

  dev->hdl = sio_open(devname, SIO_PLAY, 0);
  if (dev->hdl == NULL) {
    FLUID_LOG(FLUID_ERR, "sndio could not be opened for writing");
    goto error_recovery;
  }

  sio_initpar(&dev->par);

  dev->par.appbufsz = period_size * periods;
  dev->par.round = period_size;

  dev->par.bits = 16;
  dev->par.le = SIO_LE_NATIVE;
  dev->par.pchan = 2;
  dev->par.rate = sample_rate;

  if (!sio_setpar(dev->hdl, &dev->par)){
    FLUID_LOG(FLUID_ERR, "Can't configure sndio parameters");
    goto error_recovery;
  }

  if (!sio_getpar(dev->hdl, &dev->par)) {
    FLUID_LOG(FLUID_ERR, "Couldn't get sndio audio parameters");
    goto error_recovery;
  } else if (dev->par.pchan != 2 || dev->par.rate != sample_rate ||
      dev->par.bits != 16) {
    FLUID_LOG(FLUID_ERR, "Couldn't set sndio audio parameters as desired");
    goto error_recovery;
  }

  dev->buffer_size = dev->par.round;
  dev->buffer_byte_size = dev->par.round * dev->par.bps * dev->par.pchan;

  /* allocate the buffers. FIXME!!! don't use interleaved samples */
  dev->buffer = FLUID_MALLOC(dev->buffer_byte_size);
  if (dev->buffer == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    goto error_recovery;
  }
  dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size);
  dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size);
  if ((dev->buffer == NULL) || (dev->buffers[0] == NULL) || (dev->buffers[1] == NULL)) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    goto error_recovery;
  }

  if (!sio_start(dev->hdl)) {
    FLUID_LOG(FLUID_ERR, "Couldn't start sndio");
    goto error_recovery;
  }

  if (pthread_attr_init(&attr)) {
    FLUID_LOG(FLUID_ERR, "Couldn't initialize audio thread attributes");
    goto error_recovery;
  }

  err = pthread_create(&dev->thread, &attr, fluid_sndio_audio_run2, (void*) dev);
  if (err) {
    FLUID_LOG(FLUID_ERR, "Couldn't create audio2 thread");
    goto error_recovery;
  }

  return (fluid_audio_driver_t*) dev;

error_recovery:
  delete_fluid_sndio_audio_driver((fluid_audio_driver_t*) dev);
  return NULL;
}