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_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; }