mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-27 06:22:06 +00:00
Add support for multiple stereo outputs when callbacks are used.
This commit is contained in:
parent
908494524b
commit
64121229ea
2 changed files with 81 additions and 43 deletions
|
@ -93,8 +93,7 @@ typedef struct
|
|||
/* callback called by the task for audio rendering in dsound buffers */
|
||||
fluid_audio_channels_callback_t write;
|
||||
HANDLE quit_ev; /* Event object to request the audio task to stop */
|
||||
float *lbuf;
|
||||
float *rbuf;
|
||||
float **drybuf;
|
||||
|
||||
int bytes_per_second; /* number of bytes per second */
|
||||
DWORD buffer_byte_size; /* size of one buffer in bytes */
|
||||
|
@ -200,6 +199,7 @@ new_fluid_dsound_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t fu
|
|||
double sample_rate;
|
||||
int periods, period_size;
|
||||
int audio_channels;
|
||||
int i;
|
||||
fluid_dsound_devsel_t devsel;
|
||||
WAVEFORMATEXTENSIBLE format;
|
||||
|
||||
|
@ -224,6 +224,9 @@ new_fluid_dsound_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t fu
|
|||
/* Clear format structure*/
|
||||
ZeroMemory(&format, sizeof(WAVEFORMATEXTENSIBLE));
|
||||
|
||||
/* Set this early so that if buffer allocation failed we can free the memory */
|
||||
dev->channels_count = audio_channels * 2;
|
||||
|
||||
/* check the format */
|
||||
if(!func)
|
||||
{
|
||||
|
@ -262,13 +265,22 @@ new_fluid_dsound_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t fu
|
|||
format.Format.wBitsPerSample = 8 * sizeof(float);
|
||||
format.SubFormat = guid_float;
|
||||
format.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
dev->lbuf = FLUID_ARRAY(float, periods * period_size);
|
||||
dev->rbuf = FLUID_ARRAY(float, periods * period_size);
|
||||
if (dev->lbuf == NULL || dev->rbuf == NULL)
|
||||
dev->drybuf = FLUID_ARRAY(float*, audio_channels * 2);
|
||||
if(dev->drybuf == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto error_recovery;
|
||||
}
|
||||
FLUID_MEMSET(dev->drybuf, 0, sizeof(float*) * audio_channels * 2);
|
||||
for(i = 0; i < audio_channels * 2; ++i)
|
||||
{
|
||||
dev->drybuf[i] = FLUID_ARRAY(float, periods * period_size);
|
||||
if(dev->drybuf[i] == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto error_recovery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish to initialize the format structure */
|
||||
|
@ -305,7 +317,6 @@ new_fluid_dsound_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t fu
|
|||
dev->buffer_byte_size = period_size * dev->frame_size;
|
||||
dev->queue_byte_size = periods * dev->buffer_byte_size;
|
||||
dev->bytes_per_second = format.Format.nAvgBytesPerSec;
|
||||
dev->channels_count = format.Format.nChannels;
|
||||
|
||||
devsel.devGUID = NULL;
|
||||
|
||||
|
@ -452,6 +463,8 @@ error_recovery:
|
|||
|
||||
void delete_fluid_dsound_audio_driver(fluid_audio_driver_t *d)
|
||||
{
|
||||
int i;
|
||||
|
||||
fluid_dsound_audio_driver_t *dev = (fluid_dsound_audio_driver_t *) d;
|
||||
fluid_return_if_fail(dev != NULL);
|
||||
|
||||
|
@ -506,8 +519,15 @@ void delete_fluid_dsound_audio_driver(fluid_audio_driver_t *d)
|
|||
IDirectSound_Release(dev->direct_sound);
|
||||
}
|
||||
|
||||
FLUID_FREE(dev->lbuf);
|
||||
FLUID_FREE(dev->rbuf);
|
||||
if(dev->func)
|
||||
{
|
||||
for(i = 0; i < dev->channels_count; ++i)
|
||||
{
|
||||
FLUID_FREE(dev->drybuf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
FLUID_FREE(dev->drybuf);
|
||||
|
||||
FLUID_FREE(dev);
|
||||
}
|
||||
|
@ -689,23 +709,23 @@ static int fluid_dsound_write_processed_channels(fluid_synth_t *data, int len,
|
|||
void *channels_out[], int channels_off[],
|
||||
int channels_incr[])
|
||||
{
|
||||
int i;
|
||||
int i, ch;
|
||||
int ret;
|
||||
fluid_dsound_audio_driver_t *drv = (fluid_dsound_audio_driver_t*) data;
|
||||
float *out[2] = {drv->lbuf, drv->rbuf};
|
||||
float *lptr;
|
||||
float *rptr;
|
||||
FLUID_MEMSET(drv->lbuf, 0, len * sizeof(float));
|
||||
FLUID_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)
|
||||
float *optr[DSOUND_MAX_STEREO_CHANNELS * 2];
|
||||
for(ch = 0; ch < drv->channels_count; ++ch)
|
||||
{
|
||||
*lptr = drv->lbuf[i];
|
||||
*rptr = drv->rbuf[i];
|
||||
lptr += channels_incr[0];
|
||||
rptr += channels_incr[1];
|
||||
FLUID_MEMSET(drv->drybuf[ch], 0, len * sizeof(float));
|
||||
optr[ch] = (float*)channels_out[ch] + channels_off[ch];
|
||||
}
|
||||
ret = drv->func(drv->synth, len, 0, NULL, drv->channels_count, drv->drybuf);
|
||||
for(ch = 0; ch < drv->channels_count; ++ch)
|
||||
{
|
||||
for(i = 0; i < len; ++i)
|
||||
{
|
||||
*optr[ch] = drv->drybuf[ch][i];
|
||||
optr[ch] += channels_incr[ch];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -88,8 +88,7 @@ typedef struct
|
|||
void *synth;
|
||||
fluid_audio_func_t func;
|
||||
fluid_audio_channels_callback_t write_ptr;
|
||||
float *lbuf;
|
||||
float *rbuf;
|
||||
float **drybuf;
|
||||
|
||||
HWAVEOUT hWaveOut;
|
||||
WAVEHDR waveHeader[NB_SOUND_BUFFERS];
|
||||
|
@ -387,14 +386,24 @@ new_fluid_waveout_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t f
|
|||
|
||||
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)
|
||||
dev->drybuf = FLUID_ARRAY(float*, audio_channels * 2);
|
||||
if(dev->drybuf == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
delete_fluid_waveout_audio_driver(&dev->driver);
|
||||
return NULL;
|
||||
}
|
||||
FLUID_MEMSET(dev->drybuf, 0, sizeof(float*) * audio_channels * 2);
|
||||
for(i = 0; i < audio_channels * 2; ++i)
|
||||
{
|
||||
dev->drybuf[i] = FLUID_ARRAY(float, periods * period_size);
|
||||
if(dev->drybuf[i] == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
delete_fluid_waveout_audio_driver(&dev->driver);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get the selected device name. if none is specified, use default device. */
|
||||
|
@ -513,6 +522,8 @@ new_fluid_waveout_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t f
|
|||
|
||||
void delete_fluid_waveout_audio_driver(fluid_audio_driver_t *d)
|
||||
{
|
||||
int i;
|
||||
|
||||
fluid_waveout_audio_driver_t *dev = (fluid_waveout_audio_driver_t *) d;
|
||||
fluid_return_if_fail(dev != NULL);
|
||||
|
||||
|
@ -538,8 +549,15 @@ void delete_fluid_waveout_audio_driver(fluid_audio_driver_t *d)
|
|||
CloseHandle(dev->hQuit);
|
||||
}
|
||||
|
||||
FLUID_FREE(dev->lbuf);
|
||||
FLUID_FREE(dev->rbuf);
|
||||
if(dev->func)
|
||||
{
|
||||
for(i = 0; i < dev->channels_count; ++i)
|
||||
{
|
||||
FLUID_FREE(dev->drybuf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
FLUID_FREE(dev->drybuf);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, dev);
|
||||
}
|
||||
|
@ -549,23 +567,23 @@ static int fluid_waveout_write_processed_channels(fluid_synth_t *data, int len,
|
|||
void *channels_out[], int channels_off[],
|
||||
int channels_incr[])
|
||||
{
|
||||
int i;
|
||||
int i, ch;
|
||||
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;
|
||||
FLUID_MEMSET(drv->lbuf, 0, len * sizeof(float));
|
||||
FLUID_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)
|
||||
float *optr[WAVEOUT_MAX_STEREO_CHANNELS * 2];
|
||||
for(ch = 0; ch < drv->channels_count; ++ch)
|
||||
{
|
||||
*lptr = drv->lbuf[i];
|
||||
*rptr = drv->rbuf[i];
|
||||
lptr += channels_incr[0];
|
||||
rptr += channels_incr[1];
|
||||
FLUID_MEMSET(drv->drybuf[ch], 0, len * sizeof(float));
|
||||
optr[ch] = (float*)channels_out[ch] + channels_off[ch];
|
||||
}
|
||||
ret = drv->func(drv->synth, len, 0, NULL, drv->channels_count, drv->drybuf);
|
||||
for(ch = 0; ch < drv->channels_count; ++ch)
|
||||
{
|
||||
for(i = 0; i < len; ++i)
|
||||
{
|
||||
*optr[ch] = drv->drybuf[ch][i];
|
||||
optr[ch] += channels_incr[ch];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue