1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  * Copyright (C) 2018  Carlo Bramini
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA
20  */
21 
22 #include "fluid_synth.h"
23 #include "fluid_adriver.h"
24 #include "fluid_settings.h"
25 
26 #if WAVEOUT_SUPPORT
27 
28 #include <mmsystem.h>
29 #include <mmreg.h>
30 
31 /* Those two includes are required on Windows 9x/ME */
32 #include <ks.h>
33 #include <ksmedia.h>
34 
35 /**
36 * The driver handle multiple channels.
37 * Actually the number maximum of channels is limited to  2 * WAVEOUT_MAX_STEREO_CHANNELS.
38 * The only reason of this limitation is because we dont know how to define the mapping
39 * of speakers for stereo output number above WAVEOUT_MAX_STEREO_CHANNELS.
40 */
41 /* Maximum number of stereo outputs */
42 #define WAVEOUT_MAX_STEREO_CHANNELS 4
43 
44 static char *fluid_waveout_error(MMRESULT hr);
45 static int fluid_waveout_write_processed_channels(fluid_synth_t *data, int len,
46                                int channels_count,
47                                void *channels_out[], int channels_off[],
48                                int channels_incr[]);
49 
50 /* Speakers mapping */
51 static const DWORD channel_mask_speakers[WAVEOUT_MAX_STEREO_CHANNELS] =
52 {
53     /* 1 stereo output */
54     SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT,
55 
56     /* 2 stereo outputs */
57     SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
58     SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
59 
60     /* 3 stereo outputs */
61     SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
62     SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
63     SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
64 
65     /* 4 stereo outputs */
66     SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
67     SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
68     SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |
69     SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT
70 };
71 
72 typedef struct
73 {
74     fluid_audio_driver_t driver;
75 
76     void *synth;
77     fluid_audio_func_t func;
78     fluid_audio_channels_callback_t write_ptr;
79     float **drybuf;
80 
81     HWAVEOUT hWaveOut;
82     WAVEHDR *waveHeader;
83 
84     int periods; /* numbers of internal driver buffers */
85     int num_frames;
86 
87     HANDLE hThread;
88     DWORD  dwThread;
89 
90     int    nQuit;
91     HANDLE hQuit;
92     int channels_count; /* number of channels in audio stream */
93 
94 } fluid_waveout_audio_driver_t;
95 
96 
97 /* Thread for playing sample buffers */
fluid_waveout_synth_thread(void * data)98 static DWORD WINAPI fluid_waveout_synth_thread(void *data)
99 {
100     fluid_waveout_audio_driver_t *dev;
101     WAVEHDR                      *pWave;
102 
103     MSG msg;
104     int code;
105     /* pointers table on output first sample channels */
106     void *channels_out[WAVEOUT_MAX_STEREO_CHANNELS * 2];
107     int channels_off[WAVEOUT_MAX_STEREO_CHANNELS * 2];
108     int channels_incr[WAVEOUT_MAX_STEREO_CHANNELS * 2];
109     int i;
110 
111     dev = (fluid_waveout_audio_driver_t *)data;
112 
113     /* initialize write callback constant parameters:
114        MME expects interleaved channels in a unique buffer.
115        For example 4 channels (c1, c2, c3, c4) and n samples:
116        { s1:c1, s1:c2, s1:c3, s1:c4,  s2:c1, s2:c2, s2:c3, s2:c4,...
117          sn:c1, sn:c2, sn:c3, sn:c4 }.
118 
119        So, channels_off[], channnel_incr[] tables should initialized like this:
120          channels_off[0] = 0    channels_incr[0] = 4
121          channels_off[1] = 1    channels_incr[1] = 4
122          channels_off[2] = 2    channels_incr[2] = 4
123          channels_off[3] = 3    channels_incr[3] = 4
124 
125        channels_out[], table will be initialized later, just before calling
126        the write callback function.
127          channels_out[0] = address of dsound buffer
128          channels_out[1] = address of dsound buffer
129          channels_out[2] = address of dsound buffer
130          channels_out[3] = address of dsound buffer
131     */
132     for(i = 0; i < dev->channels_count; i++)
133     {
134         channels_off[i] = i;
135         channels_incr[i] = dev->channels_count;
136     }
137 
138     /* Forces creation of message queue */
139     PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
140 
141     for(;;)
142     {
143         code = GetMessage(&msg, NULL, 0, 0);
144 
145         if(code < 0)
146         {
147             FLUID_LOG(FLUID_ERR, "fluid_waveout_synth_thread: GetMessage() failed: '%s'", fluid_get_windows_error());
148             break;
149         }
150 
151         if(msg.message == WM_CLOSE)
152         {
153             break;
154         }
155 
156         switch(msg.message)
157         {
158         case MM_WOM_DONE:
159             pWave = (WAVEHDR *)msg.lParam;
160             dev   = (fluid_waveout_audio_driver_t *)pWave->dwUser;
161 
162             if(dev->nQuit > 0)
163             {
164                 /* Release the sample buffer */
165                 waveOutUnprepareHeader((HWAVEOUT)msg.wParam, pWave, sizeof(WAVEHDR));
166 
167                 if(--dev->nQuit == 0)
168                 {
169                     SetEvent(dev->hQuit);
170                 }
171             }
172             else
173             {
174                 /* Before calling write function, finish to initialize
175                    channels_out[] table parameter:
176                    MME expects interleaved channels in a unique buffer.
177                    So, channels_out[] table must be initialized with the address
178                    of the same buffer (lpData).
179                 */
180                 i = dev->channels_count;
181 
182                 do
183                 {
184                     channels_out[--i] = pWave->lpData;
185                 }
186                 while(i);
187 
188                 dev->write_ptr(dev->func ? (fluid_synth_t*)dev : dev->synth, dev->num_frames, dev->channels_count,
189                                channels_out, channels_off, channels_incr);
190 
191                 waveOutWrite((HWAVEOUT)msg.wParam, pWave, sizeof(WAVEHDR));
192             }
193 
194             break;
195         }
196     }
197 
198     return 0;
199 }
200 
fluid_waveout_audio_driver_settings(fluid_settings_t * settings)201 void fluid_waveout_audio_driver_settings(fluid_settings_t *settings)
202 {
203     UINT n, nDevs = waveOutGetNumDevs();
204 #ifdef _UNICODE
205     char dev_name[MAXPNAMELEN];
206 #endif
207 
208     fluid_settings_register_str(settings, "audio.waveout.device", "default", 0);
209     fluid_settings_add_option(settings, "audio.waveout.device", "default");
210 
211     for(n = 0; n < nDevs; n++)
212     {
213         WAVEOUTCAPS caps;
214         MMRESULT    res;
215 
216         res = waveOutGetDevCaps(n, &caps, sizeof(caps));
217 
218         if(res == MMSYSERR_NOERROR)
219         {
220 #ifdef _UNICODE
221             WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, dev_name, MAXPNAMELEN, 0, 0);
222             FLUID_LOG(FLUID_DBG, "Testing audio device: %s", dev_name);
223             fluid_settings_add_option(settings, "audio.waveout.device", dev_name);
224 #else
225             FLUID_LOG(FLUID_DBG, "Testing audio device: %s", caps.szPname);
226             fluid_settings_add_option(settings, "audio.waveout.device", caps.szPname);
227 #endif
228         }
229     }
230 }
231 
232 
233 /*
234  * new_fluid_waveout_audio_driver
235  * The driver handle the case of multiple stereo buffers provided by fluidsynth
236  * mixer.
237  * Each stereo buffers (left, right) are written to respective channels pair
238  * of the audio device card.
239  * For example, if the number of internal mixer buffer is 2, the audio device
240  * must have at least 4 channels:
241  * - buffer 0 (left, right) will be written to channel pair (0, 1).
242  * - buffer 1 (left, right) will be written to channel pair (2, 3).
243  *
244  * @param setting. The settings the driver looks for:
245  *  "synth.sample-rate", the sample rate.
246  *  "synth.audio-channels", the number of internal mixer stereo buffer.
247  *  "audio.periods",the number of buffers.
248  *  "audio.period-size",the size of one buffer.
249  *  "audio.sample-format",the sample format, 16bits or float.
250  *
251  * @param synth, fluidsynth synth instance to associate to the driver.
252  *
253  * Note: The number of internal mixer stereo buffer is indicated by "synth.audio-channels".
254  * If the audio device cannot handle the format or do not have enough channels,
255  * the driver fails and return NULL.
256  */
257 fluid_audio_driver_t *
new_fluid_waveout_audio_driver(fluid_settings_t * settings,fluid_synth_t * synth)258 new_fluid_waveout_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
259 {
260     return new_fluid_waveout_audio_driver2(settings, NULL, synth);
261 }
262 
263 fluid_audio_driver_t *
new_fluid_waveout_audio_driver2(fluid_settings_t * settings,fluid_audio_func_t func,void * data)264 new_fluid_waveout_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data)
265 {
266     fluid_waveout_audio_driver_t *dev = NULL;
267     fluid_audio_channels_callback_t write_ptr;
268     double sample_rate;
269     int frequency, sample_size;
270     int periods, period_size;
271     int audio_channels;
272     LPSTR ptrBuffer;
273     int lenBuffer;
274     int device;
275     int i;
276     WAVEFORMATEXTENSIBLE wfx;
277     char dev_name[MAXPNAMELEN];
278     MMRESULT errCode;
279 
280     /* Retrieve the settings */
281     fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
282     fluid_settings_getint(settings, "audio.periods", &periods);
283     fluid_settings_getint(settings, "audio.period-size", &period_size);
284     fluid_settings_getint(settings, "synth.audio-channels", &audio_channels);
285 
286     /* Clear format structure */
287     ZeroMemory(&wfx, sizeof(WAVEFORMATEXTENSIBLE));
288 
289     /* check the format */
290     if(fluid_settings_str_equal(settings, "audio.sample-format", "float") || func)
291     {
292         FLUID_LOG(FLUID_DBG, "Selected 32 bit sample format");
293 
294         sample_size = sizeof(float);
295         write_ptr = func ? fluid_waveout_write_processed_channels : fluid_synth_write_float_channels;
296         wfx.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
297         wfx.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
298     }
299     else if(fluid_settings_str_equal(settings, "audio.sample-format", "16bits"))
300     {
301         FLUID_LOG(FLUID_DBG, "Selected 16 bit sample format");
302 
303         sample_size = sizeof(short);
304         write_ptr = fluid_synth_write_s16_channels;
305         wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
306         wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
307     }
308     else
309     {
310         FLUID_LOG(FLUID_ERR, "Unhandled sample format");
311         return NULL;
312     }
313 
314     /* Set frequency to integer */
315     frequency = (int)sample_rate;
316 
317     /* Initialize the format structure */
318     wfx.Format.nChannels  = audio_channels * 2;
319 
320     if(audio_channels > WAVEOUT_MAX_STEREO_CHANNELS)
321     {
322         FLUID_LOG(FLUID_ERR, "Channels number %d exceed internal limit %d",
323                   wfx.Format.nChannels, WAVEOUT_MAX_STEREO_CHANNELS * 2);
324         return NULL;
325     }
326 
327     wfx.Format.wBitsPerSample  = sample_size * 8;
328     wfx.Format.nBlockAlign     = sample_size * wfx.Format.nChannels;
329     wfx.Format.nSamplesPerSec  = frequency;
330     wfx.Format.nAvgBytesPerSec = frequency * wfx.Format.nBlockAlign;
331     /* WAVEFORMATEXTENSIBLE extension is used only when channels number
332        is above 2.
333        When channels number is below 2, only WAVEFORMATEX structure
334        will be used by the Windows driver. This ensures compatibility with
335        Windows 9X/NT in the case these versions does not accept the
336        WAVEFORMATEXTENSIBLE structure.
337     */
338     if(wfx.Format.nChannels > 2)
339     {
340         wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
341         wfx.Format.cbSize = 22;
342         wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample;
343         wfx.dwChannelMask = channel_mask_speakers[audio_channels - 1];
344     }
345 
346     /* allocate the internal waveout buffers:
347       The length of a single buffer in bytes is dependent of period_size.
348     */
349     lenBuffer = wfx.Format.nBlockAlign * period_size;
350     /* create and clear the driver data */
351     dev = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
352                     sizeof(fluid_waveout_audio_driver_t) +
353                     lenBuffer * periods +
354                     sizeof(WAVEHDR) * periods);
355     if(dev == NULL)
356     {
357         FLUID_LOG(FLUID_ERR, "Out of memory");
358         return NULL;
359     }
360 
361     /* Assign extra memory to WAVEHDR */
362     dev->waveHeader = (WAVEHDR *)((uintptr_t)(dev + 1) + lenBuffer * periods);
363 
364     /* Save copy of synth */
365     dev->synth = data;
366     dev->func = func;
367 
368     /* Save copy of other variables */
369     dev->write_ptr = write_ptr;
370     /* number of frames in a buffer */
371     dev->num_frames = period_size;
372     /* number of buffers */
373     dev->periods = periods;
374     dev->channels_count = wfx.Format.nChannels;
375 
376     /* Set default device to use */
377     device = WAVE_MAPPER;
378 
379     if(func)
380     {
381         /* allocate extra buffer used by fluid_waveout_write_processed_channels().
382            These buffers are buffer adaptation between the rendering
383            API fluid_synth_process() and the waveout internal buffers
384            Note: the size (in bytes) of these extra buffer (drybuf[]) must be the
385            same that the size of internal waveout buffers.
386         */
387         dev->drybuf = FLUID_ARRAY(float*, audio_channels * 2);
388         if(dev->drybuf == NULL)
389         {
390             FLUID_LOG(FLUID_ERR, "Out of memory");
391             delete_fluid_waveout_audio_driver(&dev->driver);
392             return NULL;
393         }
394         FLUID_MEMSET(dev->drybuf, 0, sizeof(float*) * audio_channels * 2);
395         for(i = 0; i < audio_channels * 2; ++i)
396         {
397             /* The length of a single buffer drybuf[i] is dependent of period_size */
398             dev->drybuf[i] = FLUID_ARRAY(float, period_size);
399             if(dev->drybuf[i] == NULL)
400             {
401                 FLUID_LOG(FLUID_ERR, "Out of memory");
402                 delete_fluid_waveout_audio_driver(&dev->driver);
403                 return NULL;
404             }
405         }
406     }
407 
408     /* get the selected device name. if none is specified, use default device. */
409     if(fluid_settings_copystr(settings, "audio.waveout.device", dev_name, MAXPNAMELEN) == FLUID_OK
410             && dev_name[0] != '\0')
411     {
412         UINT nDevs = waveOutGetNumDevs();
413         UINT n;
414 #ifdef _UNICODE
415         WCHAR lpwDevName[MAXPNAMELEN];
416 
417         MultiByteToWideChar(CP_UTF8, 0, dev_name, -1, lpwDevName, MAXPNAMELEN);
418 #endif
419 
420         for(n = 0; n < nDevs; n++)
421         {
422             WAVEOUTCAPS caps;
423             MMRESULT    res;
424 
425             res = waveOutGetDevCaps(n, &caps, sizeof(caps));
426 
427             if(res == MMSYSERR_NOERROR)
428             {
429 #ifdef _UNICODE
430 
431                 if(wcsicmp(lpwDevName, caps.szPname) == 0)
432 #else
433                 if(FLUID_STRCASECMP(dev_name, caps.szPname) == 0)
434 #endif
435                 {
436                     FLUID_LOG(FLUID_DBG, "Selected audio device GUID: %s", dev_name);
437                     device = n;
438                     break;
439                 }
440             }
441         }
442     }
443 
444     do
445     {
446 
447         dev->hQuit = CreateEvent(NULL, FALSE, FALSE, NULL);
448 
449         if(dev->hQuit == NULL)
450         {
451             FLUID_LOG(FLUID_ERR, "Failed to create quit event: '%s'", fluid_get_windows_error());
452             break;
453         }
454 
455         /* Create thread which processes re-adding SYSEX buffers */
456         dev->hThread = CreateThread(
457                            NULL,
458                            0,
459                            (LPTHREAD_START_ROUTINE)
460                            fluid_waveout_synth_thread,
461                            dev,
462                            0,
463                            &dev->dwThread);
464 
465         if(dev->hThread == NULL)
466         {
467             FLUID_LOG(FLUID_ERR, "Failed to create waveOut thread: '%s'", fluid_get_windows_error());
468             break;
469         }
470 
471         errCode = waveOutOpen(&dev->hWaveOut,
472                               device,
473                               (WAVEFORMATEX *)&wfx,
474                               (DWORD_PTR)dev->dwThread,
475                               0,
476                               CALLBACK_THREAD);
477 
478         if(errCode != MMSYSERR_NOERROR)
479         {
480             FLUID_LOG(FLUID_ERR, "Failed to open waveOut device: '%s'", fluid_waveout_error(errCode));
481             break;
482         }
483 
484         /* Get pointer to sound buffer memory */
485         ptrBuffer = (LPSTR)(dev + 1);
486 
487         /* Setup the sample buffers */
488         for(i = 0; i < periods; i++)
489         {
490             /* Clear the sample buffer */
491             memset(ptrBuffer, 0, lenBuffer);
492 
493             /* Clear descriptor buffer */
494             memset(dev->waveHeader + i, 0, sizeof(WAVEHDR));
495 
496             /* Compile descriptor buffer */
497             dev->waveHeader[i].lpData         = ptrBuffer;
498             dev->waveHeader[i].dwBufferLength = lenBuffer;
499             dev->waveHeader[i].dwUser         = (DWORD_PTR)dev;
500 
501             waveOutPrepareHeader(dev->hWaveOut, &dev->waveHeader[i], sizeof(WAVEHDR));
502 
503             ptrBuffer += lenBuffer;
504         }
505 
506         /* Play the sample buffers */
507         for(i = 0; i < periods; i++)
508         {
509             waveOutWrite(dev->hWaveOut, &dev->waveHeader[i], sizeof(WAVEHDR));
510         }
511 
512         return (fluid_audio_driver_t *) dev;
513 
514     }
515     while(0);
516 
517     delete_fluid_waveout_audio_driver(&dev->driver);
518     return NULL;
519 }
520 
521 
delete_fluid_waveout_audio_driver(fluid_audio_driver_t * d)522 void delete_fluid_waveout_audio_driver(fluid_audio_driver_t *d)
523 {
524     int i;
525 
526     fluid_waveout_audio_driver_t *dev = (fluid_waveout_audio_driver_t *) d;
527     fluid_return_if_fail(dev != NULL);
528 
529     /* release all the allocated resources */
530     if(dev->hWaveOut != NULL)
531     {
532         dev->nQuit = dev->periods;
533         WaitForSingleObject(dev->hQuit, INFINITE);
534 
535         waveOutClose(dev->hWaveOut);
536     }
537 
538     if(dev->hThread != NULL)
539     {
540         PostThreadMessage(dev->dwThread, WM_CLOSE, 0, 0);
541         WaitForSingleObject(dev->hThread, INFINITE);
542 
543         CloseHandle(dev->hThread);
544     }
545 
546     if(dev->hQuit != NULL)
547     {
548         CloseHandle(dev->hQuit);
549     }
550 
551     if(dev->drybuf != NULL)
552     {
553         for(i = 0; i < dev->channels_count; ++i)
554         {
555             FLUID_FREE(dev->drybuf[i]);
556         }
557     }
558 
559     FLUID_FREE(dev->drybuf);
560 
561     HeapFree(GetProcessHeap(), 0, dev);
562 }
563 
fluid_waveout_write_processed_channels(fluid_synth_t * data,int len,int channels_count,void * channels_out[],int channels_off[],int channels_incr[])564 static int fluid_waveout_write_processed_channels(fluid_synth_t *data, int len,
565                                int channels_count,
566                                void *channels_out[], int channels_off[],
567                                int channels_incr[])
568 {
569     int i, ch;
570     int ret;
571     fluid_waveout_audio_driver_t *drv = (fluid_waveout_audio_driver_t*) data;
572     float *optr[WAVEOUT_MAX_STEREO_CHANNELS * 2];
573     for(ch = 0; ch < drv->channels_count; ++ch)
574     {
575         FLUID_MEMSET(drv->drybuf[ch], 0, len * sizeof(float));
576         optr[ch] = (float*)channels_out[ch] + channels_off[ch];
577     }
578     ret = drv->func(drv->synth, len, 0, NULL, drv->channels_count, drv->drybuf);
579     for(ch = 0; ch < drv->channels_count; ++ch)
580     {
581         for(i = 0; i < len; ++i)
582         {
583             *optr[ch] = drv->drybuf[ch][i];
584             optr[ch] += channels_incr[ch];
585         }
586     }
587     return ret;
588 }
589 
fluid_waveout_error(MMRESULT hr)590 static char *fluid_waveout_error(MMRESULT hr)
591 {
592     char *s = "Don't know why";
593 
594     switch(hr)
595     {
596     case MMSYSERR_NOERROR:
597         s = "The operation completed successfully :)";
598         break;
599 
600     case MMSYSERR_ALLOCATED:
601         s = "Specified resource is already allocated.";
602         break;
603 
604     case MMSYSERR_BADDEVICEID:
605         s = "Specified device identifier is out of range";
606         break;
607 
608     case MMSYSERR_NODRIVER:
609         s = "No device driver is present";
610         break;
611 
612     case MMSYSERR_NOMEM:
613         s = "Unable to allocate or lock memory";
614         break;
615 
616     case WAVERR_BADFORMAT:
617         s = "Attempted to open with an unsupported waveform-audio format";
618         break;
619 
620     case WAVERR_SYNC:
621         s = "The device is synchronous but waveOutOpen was called without using the WAVE_ALLOWSYNC flag";
622         break;
623     }
624 
625     return s;
626 }
627 
628 #endif /* WAVEOUT_SUPPORT */
629