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