Add support for new_fluid_audio_driver2 while using the waveout driver.

This commit is contained in:
Chris Xiong 2021-01-19 10:25:24 +08:00
parent 9562ae6009
commit 772f62fc91
3 changed files with 84 additions and 9 deletions

View file

@ -124,7 +124,7 @@ static const fluid_audriver_definition_t fluid_audio_drivers[] =
{
"waveout",
new_fluid_waveout_audio_driver,
NULL,
new_fluid_waveout_audio_driver2,
delete_fluid_waveout_audio_driver,
fluid_waveout_audio_driver_settings
},

View file

@ -105,6 +105,9 @@ void fluid_dsound_audio_driver_settings(fluid_settings_t *settings);
#if WAVEOUT_SUPPORT
fluid_audio_driver_t *new_fluid_waveout_audio_driver(fluid_settings_t *settings,
fluid_synth_t *synth);
fluid_audio_driver_t *new_fluid_waveout_audio_driver2(fluid_settings_t *settings,
fluid_audio_func_t func,
void *data);
void delete_fluid_waveout_audio_driver(fluid_audio_driver_t *p);
void fluid_waveout_audio_driver_settings(fluid_settings_t *settings);
#endif

View file

@ -49,6 +49,10 @@
#define WAVEOUT_MAX_STEREO_CHANNELS 4
static char *fluid_waveout_error(MMRESULT hr);
static int fluid_waveout_write_processed_channels(fluid_synth_t *data, int len,
int channels_count,
void *channels_out[], int channels_off[],
int channels_incr[]);
/* speakers mapping */
const static DWORD channel_mask_speakers[WAVEOUT_MAX_STEREO_CHANNELS] =
@ -81,8 +85,11 @@ typedef struct
{
fluid_audio_driver_t driver;
fluid_synth_t *synth;
void *synth;
fluid_audio_func_t func;
fluid_audio_channels_callback_t write_ptr;
float *lbuf;
float *rbuf;
HWAVEOUT hWaveOut;
WAVEHDR waveHeader[NB_SOUND_BUFFERS];
@ -191,7 +198,7 @@ static DWORD WINAPI fluid_waveout_synth_thread(void *data)
}
while(i);
dev->write_ptr(dev->synth, dev->num_frames, dev->channels_count,
dev->write_ptr(dev->func ? (fluid_synth_t*)dev : dev->synth, dev->num_frames, dev->channels_count,
channels_out, channels_off, channels_incr);
waveOutWrite((HWAVEOUT)msg.wParam, pWave, sizeof(WAVEHDR));
@ -259,11 +266,19 @@ void fluid_waveout_audio_driver_settings(fluid_settings_t *settings)
*/
fluid_audio_driver_t *
new_fluid_waveout_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
{
return new_fluid_waveout_audio_driver2(settings, NULL, synth);
}
fluid_audio_driver_t *
new_fluid_waveout_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data)
{
fluid_waveout_audio_driver_t *dev = NULL;
fluid_audio_channels_callback_t write_ptr;
double sample_rate;
int frequency, sample_size;
int periods, period_size;
int audio_channels;
LPSTR ptrBuffer;
int lenBuffer;
int device;
@ -274,18 +289,21 @@ new_fluid_waveout_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
/* Retrieve the settings */
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);
fluid_settings_getint(settings, "synth.audio-channels", &audio_channels);
/* Clear format structure */
ZeroMemory(&wfx, sizeof(WAVEFORMATEXTENSIBLE));
/* check the format */
if(fluid_settings_str_equal(settings, "audio.sample-format", "float"))
if(fluid_settings_str_equal(settings, "audio.sample-format", "float") || func)
{
GUID guid_float = {DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_IEEE_FLOAT)};
FLUID_LOG(FLUID_DBG, "Selected 32 bit sample format");
sample_size = sizeof(float);
write_ptr = fluid_synth_write_float_channels;
write_ptr = func ? fluid_waveout_write_processed_channels : fluid_synth_write_float_channels;
wfx.SubFormat = guid_float;
wfx.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
}
@ -309,9 +327,9 @@ new_fluid_waveout_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
frequency = (int)sample_rate;
/* Initialize the format structure */
wfx.Format.nChannels = synth->audio_channels * 2;
wfx.Format.nChannels = audio_channels * 2;
if(synth->audio_channels > WAVEOUT_MAX_STEREO_CHANNELS)
if(audio_channels > WAVEOUT_MAX_STEREO_CHANNELS)
{
FLUID_LOG(FLUID_ERR, "Channels number %d exceed internal limit %d",
wfx.Format.nChannels, WAVEOUT_MAX_STEREO_CHANNELS * 2);
@ -335,7 +353,7 @@ new_fluid_waveout_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfx.Format.cbSize = 22;
wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample;
wfx.dwChannelMask = channel_mask_speakers[synth->audio_channels - 1];
wfx.dwChannelMask = channel_mask_speakers[audio_channels - 1];
}
/* Calculate the length of a single buffer */
@ -353,7 +371,8 @@ new_fluid_waveout_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
}
/* Save copy of synth */
dev->synth = synth;
dev->synth = data;
dev->func = func;
/* Save copy of other variables */
dev->write_ptr = write_ptr;
@ -366,6 +385,23 @@ new_fluid_waveout_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
/* Set default device to use */
device = WAVE_MAPPER;
if(func)
{
dev->lbuf = FLUID_ARRAY(float, periods * period_size);
dev->rbuf = FLUID_ARRAY(float, periods * period_size);
if (dev->lbuf == NULL || dev->rbuf == NULL)
{
FLUID_LOG(FLUID_ERR, "Out of memory");
delete_fluid_waveout_audio_driver(&dev->driver);
return NULL;
}
}
else
{
dev->lbuf = NULL;
dev->rbuf = NULL;
}
/* get the selected device name. if none is specified, use default device. */
if(fluid_settings_copystr(settings, "audio.waveout.device", dev_name, MAXPNAMELEN) == FLUID_OK
&& dev_name[0] != '\0')
@ -507,9 +543,45 @@ void delete_fluid_waveout_audio_driver(fluid_audio_driver_t *d)
CloseHandle(dev->hQuit);
}
if(dev->lbuf != NULL)
{
FLUID_FREE(dev->lbuf);
}
if(dev->rbuf != NULL)
{
FLUID_FREE(dev->rbuf);
}
HeapFree(GetProcessHeap(), 0, dev);
}
static int fluid_waveout_write_processed_channels(fluid_synth_t *data, int len,
int channels_count,
void *channels_out[], int channels_off[],
int channels_incr[])
{
int i;
int ret;
fluid_waveout_audio_driver_t *drv = (fluid_waveout_audio_driver_t*) data;
float *out[2] = {drv->lbuf, drv->rbuf};
float *lptr;
float *rptr;
memset(drv->lbuf, 0, len * sizeof(float));
memset(drv->rbuf, 0, len * sizeof(float));
ret = drv->func(drv->synth, len, 0, NULL, 2, out);
lptr = (float*)channels_out[0] + channels_off[0];
rptr = (float*)channels_out[1] + channels_off[1];
for (i = 0; i < len; ++i)
{
*lptr = drv->lbuf[i];
*rptr = drv->rbuf[i];
lptr += channels_incr[0];
rptr += channels_incr[1];
}
return ret;
}
static char *fluid_waveout_error(MMRESULT hr)
{
char *s = "Don't know why";