fluid_portaudio.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:7k
- /* FluidSynth - A Software Synthesizer
- *
- * Copyright (C) 2003 Peter Hanappe and others.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License
- * as published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA
- */
- /* fluid_portaudio.c
- *
- * Drivers for the PortAudio API : www.portaudio.com
- * Implementation files for PortAudio on each platform have to be added
- *
- * Stephane Letz (letz@grame.fr) Grame
- * 12/20/01 Adapdation for new audio drivers
- *
- * Josh Green <jgreen@users.sourceforge.net>
- * 2009-01-28 Overhauled for PortAudio 19 API and current FluidSynth API (was broken)
- */
- #include "fluid_synth.h"
- #include "fluid_sys.h"
- #include "fluid_settings.h"
- #include "fluid_adriver.h"
- #if PORTAUDIO_SUPPORT
- #include <fcntl.h>
- #include <unistd.h>
- #include <errno.h>
- #include <portaudio.h>
- /** fluid_portaudio_driver_t
- *
- * This structure should not be accessed directly. Use audio port
- * functions instead.
- */
- typedef struct
- {
- fluid_audio_driver_t driver;
- fluid_synth_t *synth;
- fluid_audio_callback_t read;
- PaStream *stream;
- } fluid_portaudio_driver_t;
- static int
- fluid_portaudio_run (const void *input, void *output, unsigned long frameCount,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags, void *userData);
- int delete_fluid_portaudio_driver (fluid_audio_driver_t *p);
- #define PORTAUDIO_DEFAULT_DEVICE "PortAudio Default"
- void
- fluid_portaudio_driver_settings (fluid_settings_t *settings)
- {
- const PaDeviceInfo *deviceInfo;
- int numDevices;
- PaError err;
- int i;
- fluid_settings_register_str (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE, 0, NULL, NULL);
- fluid_settings_add_option (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE);
- err = Pa_Initialize();
- if (err != paNoError)
- {
- FLUID_LOG (FLUID_ERR, "Error initializing PortAudio driver: %s",
- Pa_GetErrorText (err));
- return;
- }
- numDevices = Pa_GetDeviceCount();
- if (numDevices < 0)
- {
- FLUID_LOG (FLUID_ERR, "PortAudio returned unexpected device count %d", numDevices);
- return;
- }
- for (i = 0; i < numDevices; i++)
- {
- deviceInfo = Pa_GetDeviceInfo (i);
- if ( deviceInfo->maxOutputChannels >= 2 )
- fluid_settings_add_option (settings, "audio.portaudio.device",
- deviceInfo->name);
- }
- /* done with PortAudio for now, may get reopened later */
- err = Pa_Terminate();
- if (err != paNoError)
- printf ("PortAudio termination error: %sn", Pa_GetErrorText (err) );
- }
- 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;
- }
- /* PortAudio callback
- * fluid_portaudio_run
- */
- static int
- fluid_portaudio_run (const void *input, void *output, unsigned long frameCount,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags, void *userData)
- {
- fluid_portaudio_driver_t *dev = (fluid_portaudio_driver_t *)userData;
- /* it's as simple as that: */
- dev->read (dev->synth, frameCount, output, 0, 2, output, 1, 2);
- return 0;
- }
- /*
- * delete_fluid_portaudio_driver
- */
- int
- delete_fluid_portaudio_driver(fluid_audio_driver_t *p)
- {
- fluid_portaudio_driver_t* dev;
- PaError err;
- dev = (fluid_portaudio_driver_t*)p;
- if (dev == NULL) return FLUID_OK;
- /* PortAudio section */
- if (dev->stream) Pa_CloseStream (dev->stream);
- err = Pa_Terminate();
- if (err != paNoError)
- printf ("PortAudio termination error: %sn", Pa_GetErrorText (err) );
- FLUID_FREE (dev);
- return FLUID_OK;
- }
- #endif /*#if PORTAUDIO_SUPPORT */