1 /*
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>
5 
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.
10 
11     This program is distributed in the hope that it will be useful,
nested(int a)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.
15 
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
19 */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif /* HAVE_CONFIG_H */
24 #include <stdio.h>
25 #ifndef NO_STRING_H
26 #include <string.h>
27 #else
28 #include <strings.h>
29 #endif
30 #include <mme/mme_api.h>
31 #include "timidity.h"
32 #include "aenc.h"
33 #include "audriv.h"
34 #include "timer.h"
35 
36 #define DATA_BLOCK_SIZE 2048
37 #define DATA_BLOCK_NUM  48
38 #define AUDIO_CLOSE_ID -1
39 #define IS_AUDIO_PLAY_OPEN  (play_wave_format && play_wave_format->hWave != AUDIO_CLOSE_ID)
40 #define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
41 
42 struct wave_format_t
43 {
44     HWAVE hWave;
45     PCMWAVEFORMAT format;
46     WAVEHDR waveHdr;
47     UINT DevID;
48 };
49 static struct wave_format_t *play_wave_format = NULL;
50 static MMTIME *wave_time_info = NULL;
51 static LPDWORD lpdword_buff = NULL;
52 static LPWAVEOUTCAPS wave_out_caps = NULL;
53 
54 #define AUDRIV_WRITE 1
55 
56 struct data_block_t
57 {
58     LPSTR data;
59     int data_start;
60     int data_size;
61     int blockno;
62     int in_use;			/* 0, AUDRIV_WRITE */
63     struct data_block_t *next;
64 };
65 
66 static struct data_block_t all_data_block[DATA_BLOCK_NUM];
67 static struct data_block_t *free_data_block;
68 static int data_block_length;	/* used data block length */
69 void (* audriv_error_handler)(const char *errmsg) = NULL;
70 
71 static Bool audio_write_noblocking = False;
72 static double play_start_time;
73 static long play_counter, reset_samples;
74 static int output_port = AUDRIV_OUTPUT_SPEAKER;
75 
76 char audriv_errmsg[BUFSIZ];
77 
78 static const char *mme_mmsyserr_code_string[] =
79 {
80     "no error",
81     "unspecified error",
82     "device ID out of range",
83     "driver failed enable",
84     "device already allocated",
85     "device handle is invalid",
86     "no device driver present",
87     "memory allocation error",
88     "function isn't supported",
89     "error value out of range",
90     "invalid flag passed",
91     "invalid parameter passed",
92     "handle being used",
93     "simultaneously on another",
94     "thread (eg callback)",
95     "Specified alias not found in WIN.INI",
96 };
97 
98 static const char *mme_waverr_code_sring[] =
99 {
100     "unsupported wave format",
101     "still something playing",
102     "header not prepared",
103     "device is synchronous",
104     "Device in use",
105     "Device in use",
106 };
107 
108 static const char *mme_midierr_code_sring[] =
109 {
110     "header not prepared",
111     "still something playing",
112     "no current map",
113     "hardware is still busy",
114     "port no longer connected",
115     "invalid setup",
116 };
117 
118 static const char *mme_error_code_string(MMRESULT err_code)
119 {
120     if(err_code >= TIMERR_BASE)
121     {
122 	switch(err_code)
123 	{
124 	  case TIMERR_NOCANDO:
125 	    return "request not completed";
126 	  case TIMERR_STRUCT:
127 	    return "time struct size";
128 	}
129 	return "";
130     }
131     if(err_code >= MIDIERR_BASE)
132     {
133 	err_code -= MIDIERR_BASE;
134 	if(err_code > ARRAY_SIZE(mme_midierr_code_sring))
135 	    return "";
136 	return mme_midierr_code_sring[err_code];
137     }
138     if(err_code >= WAVERR_BASE)
139     {
140 	err_code -= WAVERR_BASE;
141 	if(err_code > ARRAY_SIZE(mme_waverr_code_sring))
142 	    return "";
143 	return mme_waverr_code_sring[err_code];
144     }
145     if(err_code > ARRAY_SIZE(mme_mmsyserr_code_string))
146 	return "";
147     return mme_mmsyserr_code_string[err_code];
148 }
149 
150 static void audriv_err(const char *msg)
151 {
152     strncpy(audriv_errmsg, msg, sizeof(audriv_errmsg) - 1);
153     if(audriv_error_handler != NULL)
154 	audriv_error_handler(audriv_errmsg);
155 }
156 
157 static struct data_block_t *new_data_block()
158 {
159     struct data_block_t *p;
160     if(free_data_block == NULL)
161 	return NULL;
162     p = free_data_block;
163     free_data_block = free_data_block->next;
164     data_block_length++;
165     p->next = NULL;
166     p->data_start = 0;
167     p->data_size = DATA_BLOCK_SIZE;
168     return p;
169 }
170 
171 static void reuse_data_block(int blockno)
172 {
173     if(all_data_block[blockno].in_use)
174     {
175 	all_data_block[blockno].next = free_data_block;
176 	all_data_block[blockno].in_use = 0;
177 	free_data_block = all_data_block + blockno;
178 	data_block_length--;
179     }
180 }
181 
182 static void reset_data_block(void)
183 {
184     int i;
185 
186     all_data_block[0].blockno = 0;
187     all_data_block[0].next = all_data_block + 1;
188     for(i = 1; i < DATA_BLOCK_NUM - 1; i++)
189     {
190 	all_data_block[i].blockno = i;
191 	all_data_block[i].in_use = 0;
192 	all_data_block[i].next = all_data_block + i + 1;
193     }
194     all_data_block[i].blockno = i;
195     all_data_block[i].in_use = 0;
196     all_data_block[i].next = NULL;
197     free_data_block = all_data_block;
198     data_block_length = 0;
199 }
200 
201 Bool audriv_setup_audio(void)
202 /* �����ǥ����ν������Ԥ��ޤ���
203  * ������������ True �����Ԥ������� False ���֤��ޤ���
204  */
205 {
206     int i;
207 
208     play_wave_format = (struct wave_format_t *)
209 	mmeAllocMem(sizeof(struct wave_format_t));
210     if(play_wave_format == NULL)
211     {
212 	audriv_err(mme_error_code_string(MMSYSERR_NOMEM));
213 	return False;
214     }
215     play_wave_format->DevID = 0;
216 
217     wave_time_info = (MMTIME *)mmeAllocMem(sizeof(MMTIME));
218     if(wave_time_info == NULL)
219     {
220 	audriv_free_audio();
221 	audriv_err(mme_error_code_string(MMSYSERR_NOMEM));
222 	return False;
223     }
224 
225     lpdword_buff = (LPDWORD)mmeAllocMem(sizeof(DWORD));
226     if(lpdword_buff == NULL)
227     {
228 	audriv_free_audio();
229 	audriv_err(mme_error_code_string(MMSYSERR_NOMEM));
230 	return False;
231     }
232 
233     wave_out_caps = (LPWAVEOUTCAPS)mmeAllocMem(sizeof(WAVEOUTCAPS));
234     if(wave_out_caps == NULL)
235     {
236 	audriv_free_audio();
237 	audriv_err(mme_error_code_string(MMSYSERR_NOMEM));
238 	return False;
239     }
240 
241     all_data_block[0].data = mmeAllocBuffer(DATA_BLOCK_NUM * DATA_BLOCK_SIZE);
242 
243 #ifdef DEBUG
244     fprintf(stderr, "%d shared audio buffer memory is allocated.\n",
245 	   DATA_BLOCK_NUM * DATA_BLOCK_SIZE);
246 #endif /* DEBUG */
247 
248     if(all_data_block[0].data == NULL)
249     {
250 	audriv_free_audio();
251 	audriv_err(mme_error_code_string(MMSYSERR_NOMEM));
252 	return False;
253     }
254     for(i = 1; i < DATA_BLOCK_NUM; i++)
255 	all_data_block[i].data = all_data_block[0].data + i * DATA_BLOCK_SIZE;
256     reset_data_block();
257 
258     play_wave_format->hWave = AUDIO_CLOSE_ID;
259     play_wave_format->format.wf.wFormatTag = WAVE_FORMAT_MULAW;
260     play_wave_format->format.wf.nChannels = 1;
261     play_wave_format->format.wf.nSamplesPerSec = 8000;
262     play_wave_format->format.wf.nAvgBytesPerSec = 8000;
263     play_wave_format->format.wf.nBlockAlign = 1;
264     play_wave_format->format.wBitsPerSample = 8;
265 
266     audriv_play_open();
267     audriv_play_close();
268     return True;
269 }
270 
271 void audriv_free_audio(void)
272 /* audio �θ������Ԥ��ޤ���
273  */
274 {
275     audriv_play_close();
276 
277     if(all_data_block[0].data)
278 	mmeFreeBuffer(all_data_block[0].data);
279     all_data_block[0].data = NULL;
280 
281     if(play_wave_format)
282 	mmeFreeMem(play_wave_format);
283     play_wave_format = NULL;
284 
285     if(wave_time_info)
286 	mmeFreeMem(wave_time_info);
287     wave_time_info = NULL;
288 
289     if(lpdword_buff)
290 	mmeFreeMem(lpdword_buff);
291     lpdword_buff = NULL;
292 
293     if(wave_out_caps)
294 	mmeFreeMem(wave_out_caps);
295     wave_out_caps = NULL;
296 }
297 
298 static const char *callback_message_string(UINT msg)
299 {
300     switch(msg)
301     {
302       case WOM_OPEN:
303 	return "WOM_OPEN";
304       case WOM_CLOSE:
305 	return "WOM_CLOSE";
306       case WOM_DONE:
307 	return "WOM_DONE";
308       case WIM_OPEN:
309 	return "WIM_OPEN";
310       case WIM_CLOSE:
311 	return "WIM_CLOSE";
312       case WIM_DATA:
313 	return "WIM_DATA";
314       default:
315 	return "Unknown";
316     }
317 }
318 
319 static void audriv_callback_mme(HANDLE Hwave, UINT wMsg, DWORD dwInstance,
320 				LPARAM lParam1, LPARAM lParam2)
321 {
322 #ifdef DEBUGALL
323     fprintf(stderr, "audriv_callback_mme: mMsg=%d (%s)\n",
324 	   wMsg, callback_message_string(wMsg));
325 #endif
326 
327     if(wMsg == WOM_DONE)
328     {
329 	WAVEHDR *wp = (WAVEHDR *)lParam1;
330 #ifdef DEBUGALL
331 	fprintf(stderr, "output wp->dwUser = %d\n", wp->dwUser);
332 #endif
333 	reuse_data_block(wp->dwUser);
334     }
335 }
336 
337 #ifdef DEBUG
338 static const char *ProductID_names(WORD id)
339 {
340     switch(id)
341     {
342       case MM_MIDI_MAPPER: return "MIDI Mapper";
343       case MM_WAVE_MAPPER: return "Wave Mapper";
344       case MM_SNDBLST_MIDIOUT: return "Sound Blaster MIDI output port";
345       case MM_SNDBLST_MIDIIN: return "Sound Blaster MIDI input port";
346       case MM_SNDBLST_SYNTH: return "Sound Blaster internal synthesizer";
347       case MM_SNDBLST_WAVEOUT: return "Sound Blaster waveform output";
348       case MM_SNDBLST_WAVEIN: return "Sound Blaster waveform input";
349       case MM_ADLIB: return "Ad Lib-compatible synthesizer";
350       case MM_MPU401_MIDIOUT: return "MPU401-compatible MIDI output port";
351       case MM_MPU401_MIDIIN: return "MPU401-compatible MIDI input port";
352       case MM_PC_JOYSTICK: return "Joystick adapter";
353 
354 #ifdef MM_DIGITAL_BBA
355       case MM_DIGITAL_BBA: return "DEC BaseBoard Audio for ALPHA-AXP";
356 #endif /* MM_DIGITAL_BBA */
357 
358 #ifdef MM_DIGITAL_J300AUDIO
359       case MM_DIGITAL_J300AUDIO: return "DEC J300 TC option card";
360 #endif /* MM_DIGITAL_J300AUDIO */
361 
362 #ifdef MM_DIGITAL_MSB
363       case MM_DIGITAL_MSB: return "DEC Microsoft Sound Board compatible card";
364 #endif /* MM_DIGITAL_MSB */
365 
366 #ifdef MM_DIGITAL_IMAADPCM
367       case MM_DIGITAL_IMAADPCM: return "DEC IMA ADPCM ACM driver";
368 #endif /* MM_DIGITAL_IMAADPCM */
369     }
370     return "Unknown";
371 }
372 #endif /* DEBUG */
373 
374 Bool audriv_play_open(void)
375 {
376     MMRESULT status;
377 
378     if(IS_AUDIO_PLAY_OPEN)
379 	return True;
380 
381     play_counter = 0;
382     reset_samples = 0;
383 
384     play_wave_format->hWave = 0;
385     status = waveOutOpen(&play_wave_format->hWave,
386 			 WAVE_MAPPER,
387 			 &play_wave_format->format.wf,
388 			 audriv_callback_mme,
389 			 NULL,
390 			 CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE);
391 
392     if(status != MMSYSERR_NOERROR)
393     {
394 	audriv_err(mme_error_code_string(status));
395 	play_wave_format->hWave = AUDIO_CLOSE_ID;
396 	return False;
397     }
398 
399     status = waveOutGetID(play_wave_format->hWave,
400 			  &play_wave_format->DevID);
401     if(status != MMSYSERR_NOERROR)
402     {
403 	audriv_err(mme_error_code_string(status));
404 	audriv_play_close();
405 	return False;
406     }
407 
408     status = waveOutGetDevCaps(play_wave_format->DevID,
409 			       wave_out_caps, sizeof(WAVEOUTCAPS));
410     if(status != MMSYSERR_NOERROR)
411     {
412 	audriv_err(mme_error_code_string(status));
413 	audriv_play_close();
414 	return False;
415     }
416 
417 #ifdef DEBUG
418     fprintf(stderr, "Play Device ID: %d\n", play_wave_format->DevID);
419 #ifdef MM_MICROSOFT
420     if(wave_out_caps->wMid == MM_MICROSOFT)
421 	fputs("Manufacture: Microsoft Corp.", stderr);
422 #endif /* MM_MICROSOFT */
423 #ifdef MM_DIGITAL
424     if(wave_out_caps->wMid == MM_DIGITAL)
425 	fputs("Manufacture: Digital Eq. Corp.", stderr);
426 #endif /* MM_DIGITAL */
427 
428     fprintf(stderr, "Product: %s\n", ProductID_names(wave_out_caps->wPid));
429     fprintf(stderr, "Version of the driver: %d\n", wave_out_caps->vDriverVersion);
430     fprintf(stderr, "Product name: %s\n", wave_out_caps->szPname);
431     fprintf(stderr, "Formats supported: 0x%x\n", wave_out_caps->dwFormats);
432     fprintf(stderr, "number of sources supported: 0x%x\n", wave_out_caps->wChannels);
433     fprintf(stderr, "functionality supported by driver: 0x%x\n",
434 	   wave_out_caps->dwSupport);
435 #endif
436 
437     mmeProcessCallbacks();
438 
439     return True;
440 }
441 
442 void audriv_play_close(void)
443 {
444     if(!IS_AUDIO_PLAY_OPEN)
445 	return;
446     waveOutClose(play_wave_format->hWave);
447     mmeProcessCallbacks();
448     play_wave_format->hWave = AUDIO_CLOSE_ID;
449 }
450 
451 static long calculate_play_samples(void)
452 {
453     double es;
454 
455     if(play_counter <= 0)
456 	return 0;
457 
458     es = (double)(play_wave_format->format.wf.nSamplesPerSec
459 		  * play_wave_format->format.wf.nBlockAlign)
460 	* (get_current_calender_time() - play_start_time);
461     if(es > play_counter)
462 	return play_counter / play_wave_format->format.wf.nBlockAlign;
463     return (long)(es / play_wave_format->format.wf.nBlockAlign);
464 }
465 
466 long audriv_play_stop(void)
467 /* ���դ�¨�¤���ߤ������ľ���Υ���ץ�����֤��ޤ���
468  * audriv_play_stop() �θƤӽФ��ˤ�äơ�audio ���Ĥ��ޤ���
469  * audio �������Ĥ��Ƥ������ audriv_play_stop() ��ƤӽФ������� 0 ��
470  * �֤��ޤ���
471  * ���顼�ξ��� -1 ���֤��ޤ���
472  */
473 {
474     MMRESULT status;
475 
476     if(!IS_AUDIO_PLAY_OPEN)
477 	return 0;
478 
479     status = waveOutReset(play_wave_format->hWave);
480     if(status != MMSYSERR_NOERROR)
481     {
482 	audriv_err(mme_error_code_string(status));
483 	return -1;
484     }
485 
486     waveOutClose(play_wave_format->hWave);
487     mmeProcessCallbacks();
488     play_wave_format->hWave = AUDIO_CLOSE_ID;
489 
490     return calculate_play_samples();
491 }
492 
493 Bool audriv_is_play_open(void)
494 /* audio �����դǥ����ץ���Ƥ������ True,
495  * �Ĥ��Ƥ������ False ���֤��ޤ���
496  */
497 {
498     return IS_AUDIO_PLAY_OPEN;
499 }
500 
501 Bool audriv_set_play_volume(int volume)
502 /* ���ղ��̤� 0 �� 255 ���ϰ�������ꤷ�ޤ���0 ��̵����255 �Ϻ��粻�̡�
503  * 0 ̤���� 0��255 ��Ķ�����ͤ� 255 ��������
504  * ������������ True �����Ԥ������� False ���֤��ޤ���
505  */
506 {
507     unsigned short left, right;
508     DWORD vol;
509     MMRESULT status;
510 
511     if(volume < 0)
512 	volume = 0;
513     else if(volume > 255)
514 	volume = 255;
515 
516     left = right = ((unsigned)volume) * 257;
517     vol = ((DWORD)left | (((DWORD)right) << 16));
518 
519     status = waveOutSetVolume(play_wave_format->DevID, vol);
520     if(status != MMSYSERR_NOERROR)
521     {
522 	audriv_err(mme_error_code_string(status));
523 	return False;
524     }
525 
526     return True;
527 }
528 
529 int audriv_get_play_volume(void)
530 /* ���ղ��̤� 0 �� 255 ������ޤ���0 ��̵����255 �Ϻ��粻�̡�
531  * ���Ԥ���� -1 ���֤��������Ǥʤ����� 0 �� 255 ��β��̤��֤��ޤ���
532  */
533 {
534     MMRESULT status;
535     unsigned short left, right;
536 
537     status = waveOutGetVolume(play_wave_format->DevID, lpdword_buff);
538     if(status != MMSYSERR_NOERROR)
539     {
540 	audriv_err(mme_error_code_string(status));
541 	return -1;
542     }
543 
544     left  = (*lpdword_buff & 0xffff) / 257;
545     right = ((UINT)*lpdword_buff >> 16) / 257;
546 
547     return (int)((left + right) / 2);
548 }
549 
550 /* FIXME */
551 Bool audriv_set_play_output(int port)
552 /* audio �ν����� port ����ꤷ�ޤ���port �ˤϰʲ��Τɤ줫����ꤷ�ޤ���
553  *
554  *     AUDRIV_OUTPUT_SPEAKER	���ԡ����˽��ϡ�
555  *     AUDRIV_OUTPUT_HEADPHONE	�إåɥۥ�˽��ϡ�
556  *     AUDRIV_OUTPUT_LINE_OUT	�饤�����Ȥ˽��ϡ�
557  *
558  * ������������ True �����Ԥ������� False ���֤��ޤ���
559  */
560 {
561     switch(port)
562     {
563       case AUDRIV_OUTPUT_SPEAKER:
564       case AUDRIV_OUTPUT_HEADPHONE:
565       case AUDRIV_OUTPUT_LINE_OUT:
566 	output_port = port;
567 	break;
568       default:
569 	audriv_err("���곰�ν��ϥݡ��Ȥ����ꤵ��ޤ�����");
570 	return False;
571     }
572     return True;
573 }
574 
575 /* FIXME */
576 int audriv_get_play_output(void)
577 /* audio �ν����� port �����ޤ���
578  * ���Ԥ���� -1 ���֤�����������Ȱʲ��Τ����줫���ͤ��֤��ޤ���
579  *
580  *     AUDRIV_OUTPUT_SPEAKER	���ԡ����˽��ϡ�
581  *     AUDRIV_OUTPUT_HEADPHONE	�إåɥۥ�˽��ϡ�
582  *     AUDRIV_OUTPUT_LINE_OUT	�饤�����Ȥ˽��ϡ�
583  *
584  */
585 {
586     return output_port;
587 }
588 
589 int audriv_write(char *buff, int n)
590 /* audio �� buff �� n �Х���ʬή�����ߤޤ���
591  * audriv_set_noblock_write() ����֥�å����⡼�ɤ����ꤵ�줿
592  * ���ϡ����δؿ��θƤӽФ���¨�¤˽������֤�ޤ���
593  * �֤��ͤϼºݤ�ή�����ޤ줿�Х��ȿ��Ǥ��ꡤ��֥�å����⡼�ɤ�����
594  * ����Ƥ�����ϡ����� n ��꾯�ʤ���礬����ޤ���
595  * ���Ԥ���� -1 ���֤�����������ȡ��ºݤ�ή�����ޤ줿�Х��ȿ����֤��ޤ���
596  */
597 {
598     struct data_block_t *block;
599     int len, total, loop_cnt;
600     MMRESULT status;
601 
602     total = 0;
603     loop_cnt = 0;
604     while(n > 0)
605     {
606 	mmeProcessCallbacks();
607 
608 	if((block = new_data_block()) == NULL)
609 	{
610 	    if(audio_write_noblocking)
611 		return total;
612 	    mmeWaitForCallbacks (); /* block so we don't hog 100% of the CPU */
613 	    continue;
614 	}
615 	block->in_use = AUDRIV_WRITE;
616 	if(n <= DATA_BLOCK_SIZE)
617 	    len = n;
618 	else
619 	    len = DATA_BLOCK_SIZE;
620 	memcpy(block->data, buff + total, len);
621 	play_wave_format->waveHdr.dwBufferLength = len;
622 	play_wave_format->waveHdr.lpData = block->data;
623 	play_wave_format->waveHdr.dwUser = block->blockno;
624 	status = waveOutWrite(play_wave_format->hWave,
625 			      &play_wave_format->waveHdr,
626 			      sizeof(WAVEHDR));
627 	if(status != MMSYSERR_NOERROR)
628 	{
629 	    audriv_err(mme_error_code_string(status));
630 	    return -1;
631 	}
632 
633 	if(audriv_play_active() == 0)
634 	{
635 	    reset_samples +=
636 		play_counter / play_wave_format->format.wf.nBlockAlign;
637 	    play_counter = 0;
638 	}
639 	if(play_counter == 0)
640 	    play_start_time = get_current_calender_time();
641 	play_counter += len;
642 	total += len;
643 
644 	n -= len;
645 	loop_cnt++;
646 	if(audio_write_noblocking && loop_cnt >= DATA_BLOCK_NUM/2)
647 	    break;
648     }
649     return total;
650 }
651 
652 Bool audriv_set_noblock_write(Bool noblock)
653 /* noblock �� True ����ꤹ��ȡ�audriv_write() �ƤӽФ��ǥ֥�å����ޤ���
654  * False ����ꤹ��ȡ��ǥե���Ȥξ��֤��ᤷ�ޤ���
655  * ��������������� True �����Ԥ���� False ���֤��ޤ���
656  */
657 {
658     audio_write_noblocking = noblock;
659     return True;
660 }
661 
662 int audriv_play_active(void)
663 /* ������ʤ� 1��������Ǥʤ��ʤ� 0, ���顼�ʤ� -1 ���֤��ޤ���
664  */
665 {
666     double es;
667 
668     if(play_counter <= 0)
669 	return 0;
670     es = (double)(play_wave_format->format.wf.nSamplesPerSec
671 		  * play_wave_format->format.wf.nBlockAlign)
672 	* (get_current_calender_time() - play_start_time);
673     if(es > play_counter)
674 	return 0;
675     return 1;
676 }
677 
678 long audriv_play_samples(void)
679 /* ���߱�����Υ���ץ���֤��֤��ޤ���
680  */
681 {
682 #if 1 /* audriv_play_samples() */
683     return reset_samples + calculate_play_samples();
684 #else
685     MMRESULT status;
686     int sample;
687 
688     wave_time_info->wType = TIME_SAMPLES;
689     status = waveOutGetPosition(play_wave_format->hWave,
690 				wave_time_info,
691 				sizeof(MMTIME));
692     if(status != MMSYSERR_NOERROR)
693     {
694 	audriv_err(mme_error_code_string(status));
695 	return -1;
696     }
697     sample = (int)wave_time_info->u.sample;
698     if(sample < 0)
699 	return 0;
700     return (long)sample;
701 #endif
702 }
703 
704 long audriv_get_filled(void)
705 /* �����ǥ����Хåե���ΥХ��ȿ����֤��ޤ���
706  * ���顼�ξ��� -1 ���֤��ޤ���
707  */
708 {
709     double es;
710 
711     if(play_counter <= 0)
712 	return 0;
713     es = (double)(play_wave_format->format.wf.nSamplesPerSec *
714 		  play_wave_format->format.wf.nBlockAlign)
715 	* (get_current_calender_time() - play_start_time);
716     if(es > play_counter)
717 	return 0;
718     return play_counter - (long)es;
719 }
720 
721 const long *audriv_available_encodings(int *n_ret)
722 /* �ޥ������ݡ��Ȥ��Ƥ��뤹�٤Ƥ���沽�ꥹ�Ȥ��֤��ޤ���n_ret �ˤ�
723  * ���μ���ο������֤���ޤ�����沽����魯����ͤ�
724  * aenc.h ����������Ƥ��� enum audio_encoding_types ���ͤǤ���
725  * �֤��ͤ� free ���ƤϤʤ�ޤ���
726  */
727 {
728     static const long encoding_list[] =
729     {
730 	AENC_UNSIGBYTE,	/* WAVE_FORMAT_PCM */
731 	AENC_G711_ULAW,	/* WAVE_FORMAT_MULAW */
732 	AENC_SIGWORDL,	/* WAVE_FORMAT_PCM */
733     };
734 
735     *n_ret = 3;
736     return encoding_list;
737 }
738 
739 const long *audriv_available_sample_rates(int *n_ret)
740 /* �ޥ������ݡ��Ȥ��Ƥ��뤹�٤ƤΥ���ץ�졼�ȤΥꥹ�Ȥ��֤��ޤ���
741  * n_ret �ˤϤ��μ���ο������֤���ޤ���
742  * �֤��ͤ� free ���ƤϤʤ�ޤ���
743  */
744 {
745     static const long sample_rates[] =
746     {
747 	5512, 6615, 8000, 9600, 11025, 16000, 18900, 22050, 32000, 37800,
748 	44100, 48000
749 	};
750     *n_ret = 12;
751     return sample_rates;
752 }
753 
754 const long *audriv_available_channels(int *n_ret)
755 /* �ޥ������ݡ��Ȥ��Ƥ��뤹�٤ƤΥ���ͥ���Υꥹ�Ȥ��֤��ޤ���
756  * n_ret �ˤϤ��μ���ο������֤���ޤ���
757  * �֤��ͤ� free ���ƤϤʤ�ޤ���
758  */
759 {
760     static const long channels[] = {1, 2};
761     *n_ret = 2;
762     return channels;
763 }
764 
765 static void set_wave_format_encoding(PCMWAVEFORMAT *format, long encoding)
766 {
767     switch(encoding)
768     {
769       case AENC_UNSIGBYTE:
770 	format->wf.wFormatTag = WAVE_FORMAT_PCM;
771 	format->wBitsPerSample = 8;
772 	break;
773       case AENC_G711_ULAW:
774 	format->wf.wFormatTag = WAVE_FORMAT_MULAW;
775 	format->wBitsPerSample = 8;
776 	break;
777       case AENC_G711_ALAW:
778 	format->wf.wFormatTag = WAVE_FORMAT_ALAW;
779 	format->wBitsPerSample = 8;
780 	break;
781       case AENC_SIGWORDL:
782 	format->wf.wFormatTag = WAVE_FORMAT_PCM;
783 	format->wBitsPerSample = 16;
784 	break;
785       case AENC_UNSIGWORDL:
786 	format->wf.wFormatTag = WAVE_FORMAT_PCM;
787 	format->wBitsPerSample = 16;
788 	break;
789     }
790     format->wf.nBlockAlign =
791 	format->wf.nChannels * (format->wBitsPerSample / 8);
792 }
793 
794 Bool audriv_set_play_encoding(long encoding)
795 /* audio ���ջ�����沽��������ꤷ�ޤ���
796  * ������������ True �����Ԥ������� False ���֤��ޤ���
797  */
798 {
799     int i, n;
800     const long *enc;
801 
802     enc = audriv_available_encodings(&n);
803     for(i = 0; i < n; i++)
804 	if(enc[i] == encoding)
805 	{
806 	    set_wave_format_encoding(&play_wave_format->format, encoding);
807 	    return True;
808 	}
809     return False;
810 }
811 
812 Bool audriv_set_play_sample_rate(long sample_rate)
813 /* audio ���ջ��Υ���ץ�졼�Ȥ���ꤷ�ޤ���
814  * ������������ True �����Ԥ������� False ���֤��ޤ���
815  */
816 {
817     int i, n;
818     const long *r;
819 
820     r = audriv_available_sample_rates(&n);
821     for(i = 0; i < n; i++)
822 	if(r[i] == sample_rate)
823 	{
824 	    play_wave_format->format.wf.nSamplesPerSec = sample_rate;
825 	    play_wave_format->format.wf.nAvgBytesPerSec =
826 		play_wave_format->format.wf.nSamplesPerSec *
827 		play_wave_format->format.wf.nBlockAlign;
828 	    return True;
829 	}
830     return False;
831 }
832 
833 Bool audriv_set_play_channels(long channels)
834 /* �����ѤΥ���ͥ�������ꤷ�ޤ���
835  * ���Ԥ���� False ���֤������������ True ���֤��ޤ���
836  */
837 {
838     int i, n;
839     const long *c = audriv_available_channels(&n);
840 
841     for(i = 0; i < n; i++)
842 	if(channels == c[i])
843 	{
844 	    play_wave_format->format.wf.nChannels = channels;
845 	    play_wave_format->format.wf.nBlockAlign =
846 		channels * (play_wave_format->format.wBitsPerSample / 8);
847 	    play_wave_format->format.wf.nAvgBytesPerSec =
848 		play_wave_format->format.wf.nSamplesPerSec *
849 		play_wave_format->format.wf.nBlockAlign;
850 	    return True;
851 	}
852     return False;
853 }
854 
855 void audriv_wait_play(void)
856 /* CPU �ѥ��ϲ���ʤ��褦�ˤ��뤿��ˡ����Ū����ߤ��ޤ���*/
857 {
858     mmeWaitForCallbacks();
859 }
860