2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 Functions to play sound on the Windows audio driver (Windows 95/98/NT).
24 Modified by Masanao Izumo <mo@goice.co.jp>
29 #endif /* HAVE_CONFIG_H */
54 #include "miditrace.h"
56 int opt_wmme_device_id = -1;
57 int opt_wave_format_ext = 1;
58 int opt_wmme_buffer_bits = DEFAULT_AUDIO_BUFFER_BITS;
59 int opt_wmme_buffer_num = 64;
61 /*****************************************************************************************************************************/
63 static int open_output (void); /* 0=success, 1=warning, -1=fatal error */
64 static void close_output (void);
65 static int output_data (const uint8 * Data, size_t Size);
66 static int acntl (int request, void * arg);
67 static int detect (void);
69 /*****************************************************************************************************************************/
71 #define dpm w32_play_mode
77 PF_PCM_STREAM|PF_CAN_TRACE|PF_BUFF_FRAGM_OPT,
80 "Windows audio driver", 'd',
89 /*****************************************************************************************************************************/
95 WORD wValidBitsPerSample; /* bits of precision */
96 WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
97 WORD wReserved; /* If neither applies, set to zero. */
99 DWORD dwChannelMask; /* which channels are */ /* present in stream */
101 } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
103 typedef WAVEFORMATEXTENSIBLE *PWAVEFORMATEXTENSIBLE, *LPWAVEFORMATEXTENSIBLE;
105 #define WAVE_FORMAT_UNKNOWN 0x0000
106 #define WAVE_FORMAT_PCM 0x0001
107 #define WAVE_FORMAT_ADPCM 0x0002
108 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
109 #define WAVE_FORMAT_ALAW 0x0006
110 #define WAVE_FORMAT_MULAW 0x0007
111 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
113 #define SPEAKER_FRONT_LEFT 0x1
114 #define SPEAKER_FRONT_RIGHT 0x2
115 #define SPEAKER_FRONT_CENTER 0x4
116 #define SPEAKER_MONO (SPEAKER_FRONT_CENTER)
117 #define SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
119 /*****************************************************************************************************************************/
121 #define DIM(a) sizeof(a) / sizeof(a[0])
123 static const char * mmsyserr_code_string[] =
127 "device ID out of range",
128 "driver failed enable",
129 "device already allocated",
130 "device handle is invalid",
131 "no device driver present",
132 "memory allocation error",
133 "function isn't supported",
134 "error value out of range",
135 "invalid flag passed",
136 "invalid parameter passed",
140 static const char * waverr_code_sring[] =
142 "unsupported wave format",
143 "still something playing",
144 "header not prepared",
145 "device is synchronous",
148 static const char * MMErrorMessage(MMRESULT ErrorCode)
152 if (ErrorCode >= WAVERR_BASE)
154 ErrorCode -= WAVERR_BASE;
156 if (ErrorCode > DIM(waverr_code_sring))
158 wsprintf(s, "Unknown wave error %d", ErrorCode);
162 return waverr_code_sring[ErrorCode];
165 if (ErrorCode > DIM(mmsyserr_code_string))
167 wsprintf(s, "Unknown multimedia error %d", ErrorCode);
171 return mmsyserr_code_string[ErrorCode];
176 #ifdef OUTPUT_DEBUG_STR
177 static void DebugPrint(const char *format, ...);
178 #define DEBUGPRINT DebugPrint
180 #define DEBUGPRINT (void)
183 /*****************************************************************************************************************************/
188 int Prepared; // Non-zero if this buffer has been prepared.
193 struct MMBuffer * Next;
196 static struct MMBuffer * Buffers;
197 static volatile struct MMBuffer * FreeBuffers;
198 static volatile int NumBuffersInUse;
199 static HWAVEOUT hDevice;
200 static int BufferDelay; // in milliseconds
201 static int BufferBlockDelay; // in milliseconds
202 static DWORD CurrentTime = 0;
203 static volatile BOOL DriverClosing = FALSE;
204 static volatile BOOL OutputWorking = FALSE;
205 static const int AllowSynchronousWaveforms = 1;
206 static int data_block_size;
207 static int data_block_num = 64;
208 static int data_block_trunc_size = sizeof(int16) * 2 * (1L << DEFAULT_AUDIO_BUFFER_BITS);
210 /*****************************************************************************************************************************/
212 static void BufferPoolReset(void)
216 DEBUGPRINT("Resetting buffer pool...\n");
217 Buffers[0].Number = 0;
218 Buffers[0].Prepared = 0;
219 Buffers[0].Next = &Buffers[1];
220 for (i = 1; i < data_block_num - 1; i++)
222 Buffers[i].Number = i;
223 Buffers[i].Prepared = 0;
224 Buffers[i].Next = &Buffers[i + 1];
226 Buffers[i].Number = i;
227 Buffers[i].Prepared = 0;
228 Buffers[i].Next = NULL;
229 FreeBuffers = &Buffers[0];
231 DEBUGPRINT("Buffer pool reset.\n", NumBuffersInUse);
234 static struct MMBuffer * GetBuffer()
238 DEBUGPRINT("%2d: Getting buffer...\n", NumBuffersInUse);
239 EnterCriticalSection(&critSect);
242 b = (struct MMBuffer *)FreeBuffers;
243 FreeBuffers = FreeBuffers->Next;
245 /** If this buffer is still prepared we can safely unprepare it because we got it from the free buffer list. **/
248 waveOutUnprepareHeader(hDevice, (LPWAVEHDR) b->Head, sizeof(WAVEHDR));
255 LeaveCriticalSection(&critSect);
256 DEBUGPRINT("%2d: Got buffer.\n", NumBuffersInUse);
260 static void PutBuffer(struct MMBuffer * b)
262 DEBUGPRINT("%2d: Putting buffer...\n", NumBuffersInUse);
263 b->Next = (struct MMBuffer *)FreeBuffers;
266 DEBUGPRINT("%2d: Buffer put.\n", NumBuffersInUse);
269 static void CALLBACK OnPlaybackEvent(HWAVE hWave, UINT Msg, DWORD_PTR UserData, DWORD_PTR Param1, DWORD_PTR Param2)
271 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Msg: 0x%08X, Num. buffers in use: %d", Msg, NumBuffersInUse);
275 DEBUGPRINT("%2d: Device opened.\n", NumBuffersInUse);
278 DEBUGPRINT("%2d: Device closed.\n", NumBuffersInUse);
281 EnterCriticalSection(&critSect);
282 PutBuffer(&Buffers[((WAVEHDR *)Param1)->dwUser]);
283 LeaveCriticalSection(&critSect);
286 DEBUGPRINT("%2d: Unknown play back event 0x%08X.\n", NumBuffersInUse, Msg);
291 static void print_device_list(void)
296 DEVICELIST device[DEVLIST_MAX];
298 num = waveOutGetNumDevs();
300 for(i = 0 ; i < num && i < DEVLIST_MAX ; i++){
301 if (MMSYSERR_NOERROR == waveOutGetDevCaps((UINT)i, &woc, sizeof(woc)) ){
302 device[list_num].deviceID=i;
303 strcpy(device[list_num].name, woc.szPname);
307 for(i=0;i<list_num;i++){
308 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%2d %s", device[i].deviceID, device[i].name);
312 /*****************************************************************************************************************************/
314 static int open_output(void)
317 WAVEFORMATEXTENSIBLE wfe = {0};
318 WAVEFORMATEX *pwf = NULL;
321 UINT uDeviceID, DeviceID;
325 GUID guid_WAVE_FORMAT = {WAVE_FORMAT_UNKNOWN,0x0000,0x0010,{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
327 /** Check if there is at least one audio device. **/
328 if (waveOutGetNumDevs() == 0)
330 ctl->cmsg (CMSG_ERROR, VERB_NORMAL, "No audio devices present!");
333 opt_wmme_device_id = opt_output_device_id != -3 ? opt_output_device_id : opt_wmme_device_id;
334 if (opt_wmme_device_id == -2){
338 /** They can't mean these. **/
339 dpm.encoding &= ~(PE_BYTESWAP);
340 if (dpm.encoding & (PE_16BIT | PE_24BIT | PE_32BIT | PE_F32BIT | PE_64BIT | PE_F64BIT)){
341 dpm.encoding |= PE_SIGNED;
342 }else // 8bit PE_ULAW PE_ALAW only unsigned
343 dpm.encoding &= ~PE_SIGNED;
344 format_ext = (dpm.encoding & (PE_ULAW | PE_ALAW)) ? 0 : opt_wave_format_ext;
347 memcpy(&wfe.SubFormat, &guid_WAVE_FORMAT, sizeof(GUID));
348 pwf->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
349 pwf->cbSize = (WORD)22;
351 pwf = (WAVEFORMATEX *)&wfe;
352 pwf->cbSize = (WORD)0;
354 if(dpm.encoding & PE_16BIT){
356 wfe.SubFormat.Data1 = WAVE_FORMAT_PCM;
357 wfe.Samples.wValidBitsPerSample = 16;
358 pwf->wBitsPerSample = (WORD) 16;
360 pwf->wFormatTag = WAVE_FORMAT_PCM;
361 pwf->wBitsPerSample = (WORD) 16;
363 }else if(dpm.encoding & PE_24BIT){
365 wfe.SubFormat.Data1 = WAVE_FORMAT_PCM;
366 wfe.Samples.wValidBitsPerSample = 24;
367 pwf->wBitsPerSample = (WORD) 24;
369 pwf->wFormatTag = WAVE_FORMAT_PCM;
370 pwf->wBitsPerSample = (WORD) 24;
372 }else if(dpm.encoding & PE_32BIT){
374 wfe.SubFormat.Data1 = WAVE_FORMAT_PCM;
375 wfe.Samples.wValidBitsPerSample = 32;
376 pwf->wBitsPerSample = (WORD) 32;
378 pwf->wFormatTag = WAVE_FORMAT_PCM;
379 pwf->wBitsPerSample = (WORD) 32;
381 }else if(dpm.encoding & PE_F32BIT){
383 wfe.SubFormat.Data1 = WAVE_FORMAT_IEEE_FLOAT;
384 wfe.Samples.wValidBitsPerSample = 32;
385 pwf->wBitsPerSample = (WORD) 32;
387 pwf->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
388 pwf->wBitsPerSample = (WORD) 32;
390 }else if(dpm.encoding & PE_64BIT){
392 wfe.SubFormat.Data1 = WAVE_FORMAT_PCM;
393 wfe.Samples.wValidBitsPerSample = 64;
394 pwf->wBitsPerSample = (WORD) 64;
396 pwf->wFormatTag = WAVE_FORMAT_PCM;
397 pwf->wBitsPerSample = (WORD) 64;
399 }else if(dpm.encoding & PE_F64BIT){
401 wfe.SubFormat.Data1 = WAVE_FORMAT_IEEE_FLOAT;
402 wfe.Samples.wValidBitsPerSample = 64;
403 pwf->wBitsPerSample = (WORD) 64;
405 pwf->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
406 pwf->wBitsPerSample = (WORD) 64;
408 }else if(dpm.encoding & PE_ALAW){
410 wfe.SubFormat.Data1 = WAVE_FORMAT_ALAW;
411 wfe.Samples.wValidBitsPerSample = 8;
412 pwf->wBitsPerSample = (WORD) 8;
414 pwf->wFormatTag = WAVE_FORMAT_ALAW;
415 pwf->wBitsPerSample = (WORD) 8;
417 }else if(dpm.encoding & PE_ULAW){
419 wfe.SubFormat.Data1 = WAVE_FORMAT_MULAW;
420 wfe.Samples.wValidBitsPerSample = 8;
421 pwf->wBitsPerSample = (WORD) 8;
423 pwf->wFormatTag = WAVE_FORMAT_MULAW;
424 pwf->wBitsPerSample = (WORD) 8;
428 wfe.SubFormat.Data1 = WAVE_FORMAT_PCM;
429 wfe.Samples.wValidBitsPerSample = 8;
430 pwf->wBitsPerSample = (WORD) 8;
432 pwf->wFormatTag = WAVE_FORMAT_PCM;
433 pwf->wBitsPerSample = (WORD) 8;
436 pwf->nChannels = (WORD)dpm.encoding & PE_MONO ? 1 : 2;
437 pwf->nSamplesPerSec = (DWORD)dpm.rate;
438 pwf->nBlockAlign = (WORD)(pwf->nChannels * pwf->wBitsPerSample / 8);
439 pwf->nAvgBytesPerSec = (DWORD)pwf->nSamplesPerSec * pwf->nBlockAlign;
440 wfe.dwChannelMask = pwf->nChannels == 1 ? SPEAKER_MONO : SPEAKER_STEREO;
441 if (dpm.extra_param[0] < 2)
443 ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Too small -B option: %d,X", dpm.extra_param[0]);
444 dpm.extra_param[0] = 2;
446 if (audio_buffer_bits < 7)
448 ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Too small -B option: X,%d", audio_buffer_bits);
449 audio_buffer_bits = 7;
451 /** check buffer size **/
452 tmp = dpm.extra_param[0] * audio_buffer_size;
455 ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Too small -B option: %d,%d", dpm.extra_param[0], audio_buffer_bits);
456 dpm.extra_param[0] = DEFAULT_AUDIO_BUFFER_NUM;
457 audio_buffer_bits = DEFAULT_AUDIO_BUFFER_BITS;
459 data_block_num = dpm.extra_param[0];
460 data_block_size = audio_buffer_size;
461 data_block_trunc_size = data_block_size * pwf->nBlockAlign;
462 /** Open the device. **/
463 DEBUGPRINT("Opening device...\n");
465 DriverClosing = FALSE;
466 uDeviceID = opt_wmme_device_id == -1 ? WAVE_MAPPER : (UINT)opt_wmme_device_id;
467 if (AllowSynchronousWaveforms)
468 Result = waveOutOpen(&hDevice, uDeviceID, (WAVEFORMATEX *) &wfe, (DWORD_PTR) OnPlaybackEvent, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
470 Result = waveOutOpen(&hDevice, uDeviceID, (WAVEFORMATEX *) &wfe, (DWORD_PTR) OnPlaybackEvent, 0, CALLBACK_FUNCTION);
473 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't open audio device: encoding=<%s>, rate=<%d>, ch=<%d>: %s", output_encoding_string(dpm.encoding), dpm.rate, pwf->nChannels, MMErrorMessage(Result));
478 DEBUGPRINT("Device opened.\n");
480 /** Get the device ID. **/
482 waveOutGetID(hDevice, &DeviceID);
483 /** Get the device capabilities. **/
484 memset(&woc, 0, sizeof(WAVEOUTCAPS));
485 Result = waveOutGetDevCaps(DeviceID, &woc, sizeof(WAVEOUTCAPS));
486 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Device ID: %d", DeviceID);
487 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Manufacture ID: %d", woc.wMid);
488 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Product ID: %d", woc.wPid);
489 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Driver version: %d", woc.vDriverVersion);
490 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Product name: %s", woc.szPname);
491 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Formats supported: 0x%08X", woc.dwFormats);
492 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Max. channels: %d", woc.wChannels);
493 ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Supported features: 0x%08X", woc.dwSupport);
494 /** Calculate the buffer delay. **/
495 BufferDelay = data_block_size * data_block_num * 1000 / dpm.rate;
496 BufferBlockDelay = data_block_size * 1000 / dpm.rate / 4;
497 /** Create the buffer pool. **/
498 Buffers = (struct MMBuffer *) safe_malloc(data_block_num * sizeof(struct MMBuffer));
499 for (i = 0; i < data_block_num; i++)
504 b->hData = GlobalAlloc(GMEM_ZEROINIT, data_block_trunc_size);
505 b->Data = GlobalLock (b->hData);
506 b->hHead = GlobalAlloc(GMEM_ZEROINIT, sizeof(WAVEHDR));
507 b->Head = GlobalLock (b->hHead);
510 /** Set the file descriptor. **/
515 static void close_output(void)
521 /** WaitForAllBuffers **/
522 DEBUGPRINT("%2d: Waiting for all buffers to be dequeued...\n", NumBuffersInUse);
524 EnterCriticalSection(&critSect);
525 flg = (NumBuffersInUse || OutputWorking) ? 1 : 0;
526 LeaveCriticalSection(&critSect);
530 DEBUGPRINT("%2d: All buffers dequeued.\n", NumBuffersInUse);
532 DEBUGPRINT("Closing device...\n");
533 waveOutReset(hDevice);
534 waveOutClose(hDevice);
535 DEBUGPRINT("Device closed.\n");
536 /** Free all buffers. **/
537 for (i = 0; i < data_block_num; i++)
539 struct MMBuffer * block;
542 GlobalUnlock(block->hHead);
543 GlobalFree (block->hHead);
544 GlobalUnlock(block->hData);
545 GlobalFree (block->hData);
549 /** Reset the file descriptor. **/
553 static int output_data(const uint8 *Data, size_t Size)
558 const int32 max_continue = 1164;
562 OutputWorking = TRUE;
566 while (!DriverClosing && dpm.fd != -1 && s > 0 && c > 0)
573 if ((b = GetBuffer()) == NULL)
575 DEBUGPRINT("%2d: WaitForBuffer %dms...\n", NumBuffersInUse, BufferBlockDelay);
576 Sleep(BufferBlockDelay); /** WaitForBuffer **/
580 if (DriverClosing || dpm.fd == -1) {
583 n = (s <= data_block_trunc_size) ? s : data_block_trunc_size;
584 CopyMemory(b->Data, d, n);
586 wh->dwBufferLength = n;
587 wh->lpData = b->Data;
588 wh->dwUser = b->Number;
589 /** Prepare the buffer. **/
590 DEBUGPRINT("%2d: Preparing buffer %d...\n", NumBuffersInUse, wh->dwUser);
591 Result = waveOutPrepareHeader(hDevice, wh, sizeof(WAVEHDR));
594 DEBUGPRINT("%2d: Buffer preparation failed.\n", NumBuffersInUse);
595 ctl->cmsg (CMSG_ERROR, VERB_NORMAL, "waveOutPrepareHeader(): %s", MMErrorMessage(Result));
600 DEBUGPRINT("%2d: Buffer %d prepared.\n", NumBuffersInUse, wh->dwUser);
603 /** Queue the buffer. **/
604 DEBUGPRINT("%2d: Queueing buffer %d...\n", NumBuffersInUse, wh->dwUser);
605 Result = waveOutWrite(hDevice, wh, sizeof(WAVEHDR));
608 DEBUGPRINT("%2d: Buffer queueing failed.\n", NumBuffersInUse);
609 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "waveOutWrite(): %s", MMErrorMessage(Result));
614 DEBUGPRINT("%2d: Buffer %d queued.\n", NumBuffersInUse, wh->dwUser);
620 OutputWorking = FALSE;
624 static int acntl(int request, void *arg)
629 *(int *)arg = (data_block_num-1) * data_block_trunc_size;
632 case PM_REQ_GETFILLABLE:
633 *(int *)arg = (data_block_num - NumBuffersInUse - 1) * data_block_size;
636 case PM_REQ_GETFILLED:
637 *(int *)arg = NumBuffersInUse * data_block_trunc_size;
641 DEBUGPRINT("Resetting audio device.\n");
642 waveOutReset(hDevice);
645 DEBUGPRINT("Audio device reset.\n");
653 case PM_REQ_PLAY_START: /* Called just before playing */
654 case PM_REQ_PLAY_END: /* Called just after playing */
660 static int detect(void)
662 if (waveOutGetNumDevs() == 0)
663 return 0; /* not found */
664 return 1; /* found */
667 /*****************************************************************************************************************************/
669 int wmme_device_list(DEVICELIST *device)
674 num = waveOutGetNumDevs();
675 for(i = -1 ; i < num && i < (DEVLIST_MAX - 2) ; i++){ // -1, 0
676 waveOutGetDevCaps((UINT)i, &woc, sizeof(woc));
677 device[i+1].deviceID=i;
678 strcpy(device[i+1].name, woc.szPname);