1 /* fhandler_dev_dsp: code to emulate OSS sound model /dev/dsp
3 Written by Andy Younger (andy@snoogie.demon.co.uk)
4 Extended by Gerd Spalink (Gerd.Spalink@t-online.de)
5 to support recording from the audio input
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 #include <sys/soundcard.h>
24 /*------------------------------------------------------------------------
25 Simple encapsulation of the win32 audio device.
28 1. Audio structures are malloced just before the first read or
29 write to /dev/dsp. The actual buffer size is determined at that time,
30 such that one buffer holds about 125ms of audio data.
31 At the time of this writing, 12 buffers are allocated,
32 so that up to 1.5 seconds can be buffered within Win32.
33 The buffer size can be queried with the ioctl SNDCTL_DSP_GETBLKSIZE,
34 but for this implementation only returns meaningful results if
35 sampling rate, number of channels and number of bits per sample
36 are not changed afterwards.
37 The audio structures are freed when the device is reset or closed,
38 and they are not passed to exec'ed processes.
39 The dev_ member is cleared after a fork. This forces the child
40 to reopen the audio device._
42 2. Every open call creates a new instance of the handler. After a
43 successful open, every subsequent open from the same process
44 to the device fails with EBUSY.
45 The structures are shared between duped handles, but not with
46 children. They only inherit the settings from the parent.
49 enum { DEFAULT_BLOCKS
= 12, MAX_BLOCKS
= 256 };
51 class fhandler_dev_dsp::Audio
52 { // This class contains functionality common to Audio_in and Audio_out
54 Audio (fhandler_dev_dsp
*my_fh
);
60 void setconvert (int format
);
61 void convert_none (unsigned char *buffer
, int size_bytes
) { }
62 void convert_U8_S8 (unsigned char *buffer
, int size_bytes
);
63 void convert_S16LE_U16LE (unsigned char *buffer
, int size_bytes
);
64 void convert_S16LE_U16BE (unsigned char *buffer
, int size_bytes
);
65 void convert_S16LE_S16BE (unsigned char *buffer
, int size_bytes
);
66 void fillFormat (WAVEFORMATEX
* format
,
67 int rate
, int bits
, int channels
);
68 static unsigned blockSize (double ms
, int rate
, int bits
, int channels
);
69 void (fhandler_dev_dsp::Audio::*convert_
)
70 (unsigned char *buffer
, int size_bytes
);
72 int bufferIndex_
; // offset into pHdr_->lpData
73 WAVEHDR
*pHdr_
; // data to be filled by write
74 WAVEHDR wavehdr_
[MAX_BLOCKS
];
75 char *bigwavebuffer_
; // audio samples only
76 // Member variables below must be locked
77 queue
*Qisr2app_
; // blocks passed from wave callback
82 class fhandler_dev_dsp::Audio::queue
83 { // non-blocking fixed size queues for buffer management
85 queue (int depth
= 4);
88 bool send (WAVEHDR
*); // queue an item, returns true if successful
89 bool recv (WAVEHDR
**); // retrieve an item, returns true if successful
91 int query (); // return number of items queued
92 inline void lock () { EnterCriticalSection (&lock_
); }
93 inline void unlock () { LeaveCriticalSection (&lock_
); }
94 inline void dellock () { debug_printf ("Deleting Critical Section"); DeleteCriticalSection (&lock_
); }
95 bool isvalid () { return storage_
; }
97 CRITICAL_SECTION lock_
;
104 static void CALLBACK
waveOut_callback (HWAVEOUT hWave
, UINT msg
,
105 DWORD_PTR instance
, DWORD_PTR param1
,
108 class fhandler_dev_dsp::Audio_out
: public Audio
111 Audio_out (fhandler_dev_dsp
*my_fh
) : Audio (my_fh
) {}
113 void fork_fixup (HANDLE parent
);
114 bool query (int rate
, int bits
, int channels
);
116 void stop (bool immediately
= false);
117 int write (const char *pSampleData
, int nBytes
);
118 void buf_info (audio_buf_info
*p
, int rate
, int bits
, int channels
);
119 static void default_buf_info (audio_buf_info
*p
, int rate
, int bits
, int channels
);
120 void callback_sampledone (WAVEHDR
*pHdr
);
121 bool parsewav (const char *&pData
, int &nBytes
,
122 int rate
, int bits
, int channels
);
125 void init (unsigned blockSize
);
126 void waitforallsent ();
127 bool waitforspace ();
130 HWAVEOUT dev_
; // The wave device
131 /* Private copies of audiofreq_, audiobits_, audiochannels_,
132 possibly set from wave file */
137 friend fhandler_dev_dsp
;
140 static void CALLBACK
waveIn_callback (HWAVEIN hWave
, UINT msg
,
141 DWORD_PTR instance
, DWORD_PTR param1
,
144 class fhandler_dev_dsp::Audio_in
: public Audio
147 Audio_in (fhandler_dev_dsp
*my_fh
) : Audio (my_fh
) {}
149 void fork_fixup (HANDLE parent
);
150 bool query (int rate
, int bits
, int channels
);
151 bool start (int rate
, int bits
, int channels
);
153 bool read (char *pSampleData
, int &nBytes
);
154 void buf_info (audio_buf_info
*p
, int rate
, int bits
, int channels
);
155 static void default_buf_info (audio_buf_info
*p
, int rate
, int bits
, int channels
);
156 void callback_blockfull (WAVEHDR
*pHdr
);
159 bool init (unsigned blockSize
);
160 bool queueblock (WAVEHDR
*pHdr
);
161 bool waitfordata (); // blocks until we have a good pHdr_ unless O_NONBLOCK
166 /* --------------------------------------------------------------------
169 // Simple fixed length FIFO queue implementation for audio buffer management
170 fhandler_dev_dsp::Audio::queue::queue (int depth
)
172 // allow space for one extra object in the queue
173 // so we can distinguish full and empty status
175 storage_
= new WAVEHDR
*[depth_
+ 1];
178 fhandler_dev_dsp::Audio::queue::~queue ()
184 fhandler_dev_dsp::Audio::queue::reset ()
186 /* When starting, after reset and after fork */
188 debug_printf ("InitializeCriticalSection");
189 memset (&lock_
, 0, sizeof (lock_
));
190 InitializeCriticalSection (&lock_
);
194 fhandler_dev_dsp::Audio::queue::send (WAVEHDR
*x
)
198 if (query () == depth_
)
199 system_printf ("Queue overflow");
203 if (++tail_
> depth_
)
212 fhandler_dev_dsp::Audio::queue::recv (WAVEHDR
**x
)
218 *x
= storage_
[head_
];
219 if (++head_
> depth_
)
228 fhandler_dev_dsp::Audio::queue::query ()
230 int n
= tail_
- head_
;
236 // Audio class implements functionality need for both read and write
237 fhandler_dev_dsp::Audio::Audio (fhandler_dev_dsp
*my_fh
)
239 bigwavebuffer_
= NULL
;
241 Qisr2app_
= new queue (fh
->fragstotal_
);
242 convert_
= &fhandler_dev_dsp::Audio::convert_none
;
245 fhandler_dev_dsp::Audio::~Audio ()
249 delete[] bigwavebuffer_
;
253 fhandler_dev_dsp::Audio::isvalid ()
255 return bigwavebuffer_
&& Qisr2app_
&& Qisr2app_
->isvalid ();
259 fhandler_dev_dsp::Audio::setconvert (int format
)
264 convert_
= &fhandler_dev_dsp::Audio::convert_U8_S8
;
265 debug_printf ("U8_S8");
268 convert_
= &fhandler_dev_dsp::Audio::convert_S16LE_U16LE
;
269 debug_printf ("S16LE_U16LE");
272 convert_
= &fhandler_dev_dsp::Audio::convert_S16LE_U16BE
;
273 debug_printf ("S16LE_U16BE");
276 convert_
= &fhandler_dev_dsp::Audio::convert_S16LE_S16BE
;
277 debug_printf ("S16LE_S16BE");
280 convert_
= &fhandler_dev_dsp::Audio::convert_none
;
281 debug_printf ("none");
286 fhandler_dev_dsp::Audio::convert_U8_S8 (unsigned char *buffer
,
289 while (size_bytes
-- > 0)
291 *buffer
^= (unsigned char)0x80;
297 fhandler_dev_dsp::Audio::convert_S16LE_U16BE (unsigned char *buffer
,
300 int size_samples
= size_bytes
/ 2;
301 unsigned char hi
, lo
;
302 while (size_samples
-- > 0)
307 *buffer
++ = hi
^ (unsigned char)0x80;
312 fhandler_dev_dsp::Audio::convert_S16LE_U16LE (unsigned char *buffer
,
315 int size_samples
= size_bytes
/ 2;
316 while (size_samples
-- > 0)
319 *buffer
^= (unsigned char)0x80;
325 fhandler_dev_dsp::Audio::convert_S16LE_S16BE (unsigned char *buffer
,
328 int size_samples
= size_bytes
/ 2;
329 unsigned char hi
, lo
;
330 while (size_samples
-- > 0)
340 fhandler_dev_dsp::Audio::fillFormat (WAVEFORMATEX
* format
,
341 int rate
, int bits
, int channels
)
343 memset (format
, 0, sizeof (*format
));
344 format
->wFormatTag
= WAVE_FORMAT_PCM
;
345 format
->wBitsPerSample
= bits
;
346 format
->nChannels
= channels
;
347 format
->nSamplesPerSec
= rate
;
348 format
->nAvgBytesPerSec
= format
->nSamplesPerSec
* format
->nChannels
350 format
->nBlockAlign
= format
->nChannels
* (bits
/ 8);
353 // calculate a good block size
355 fhandler_dev_dsp::Audio::blockSize (double ms
, int rate
, int bits
, int channels
)
358 blockSize
= ms
* ((bits
/ 8) * channels
* rate
) / 1000;
359 // round up to multiple of 64
365 //=======================================================================
367 fhandler_dev_dsp::Audio_out::fork_fixup (HANDLE parent
)
370 It will be necessary to reset the queue, open the device
371 and create a lock when writing */
372 debug_printf ("parent=%p", parent
);
378 fhandler_dev_dsp::Audio_out::query (int rate
, int bits
, int channels
)
383 fillFormat (&format
, rate
, bits
, channels
);
384 rc
= waveOutOpen (NULL
, WAVE_MAPPER
, &format
, 0L, 0L, WAVE_FORMAT_QUERY
);
385 debug_printf ("%u = waveOutOpen(freq=%d bits=%d channels=%d)", rc
, rate
, bits
, channels
);
386 return (rc
== MMSYSERR_NOERROR
);
390 fhandler_dev_dsp::Audio_out::start ()
398 /* In case of fork bigwavebuffer may already exist */
400 bigwavebuffer_
= new char[fh
->fragstotal_
* fh
->fragsize_
];
405 fillFormat (&format
, freq_
, bits_
, channels_
);
406 rc
= waveOutOpen (&dev_
, WAVE_MAPPER
, &format
, (DWORD_PTR
) waveOut_callback
,
407 (DWORD_PTR
) this, CALLBACK_FUNCTION
);
408 if (rc
== MMSYSERR_NOERROR
)
409 init (fh
->fragsize_
);
411 debug_printf ("%u = waveOutOpen(freq=%d bits=%d channels=%d)", rc
, freq_
, bits_
, channels_
);
413 return (rc
== MMSYSERR_NOERROR
);
417 fhandler_dev_dsp::Audio_out::stop (bool immediately
)
422 debug_printf ("dev_=%p", dev_
);
427 sendcurrent (); // force out last block whatever size..
428 waitforallsent (); // block till finished..
431 rc
= waveOutReset (dev_
);
432 debug_printf ("%u = waveOutReset()", rc
);
433 while (Qisr2app_
->recv (&pHdr
))
435 rc
= waveOutUnprepareHeader (dev_
, pHdr
, sizeof (WAVEHDR
));
436 debug_printf ("%u = waveOutUnprepareHeader(%p)", rc
, pHdr
);
439 no_thread_exit_protect
for_now (true);
440 rc
= waveOutClose (dev_
);
441 debug_printf ("%u = waveOutClose()", rc
);
443 Qisr2app_
->dellock ();
448 fhandler_dev_dsp::Audio_out::init (unsigned blockSize
)
452 // internally queue all of our buffer for later use by write
454 for (i
= 0; i
< fh
->fragstotal_
; i
++)
456 wavehdr_
[i
].lpData
= &bigwavebuffer_
[i
* blockSize
];
457 wavehdr_
[i
].dwUser
= (int) blockSize
;
458 wavehdr_
[i
].dwFlags
= 0;
459 if (!Qisr2app_
->send (&wavehdr_
[i
]))
461 system_printf ("Internal Error i=%d", i
);
462 break; // should not happen
469 fhandler_dev_dsp::Audio_out::write (const char *pSampleData
, int nBytes
)
471 int bytes_to_write
= nBytes
;
472 while (bytes_to_write
!= 0)
473 { // Block if all blocks used until at least one is free
474 if (!waitforspace ())
476 if (bytes_to_write
!= nBytes
)
481 int sizeleft
= (int)pHdr_
->dwUser
- bufferIndex_
;
482 if (bytes_to_write
< sizeleft
)
483 { // all data fits into the current block, with some space left
484 memcpy (&pHdr_
->lpData
[bufferIndex_
], pSampleData
, bytes_to_write
);
485 bufferIndex_
+= bytes_to_write
;
490 { // data will fill up the current block
491 memcpy (&pHdr_
->lpData
[bufferIndex_
], pSampleData
, sizeleft
);
492 bufferIndex_
+= sizeleft
;
494 pSampleData
+= sizeleft
;
495 bytes_to_write
-= sizeleft
;
498 return nBytes
- bytes_to_write
;
502 fhandler_dev_dsp::Audio_out::buf_info (audio_buf_info
*p
,
503 int rate
, int bits
, int channels
)
507 /* If the device is running we use the internal values,
508 possibly set from the wave file. */
509 p
->fragstotal
= fh
->fragstotal_
;
510 p
->fragsize
= fh
->fragsize_
;
511 p
->fragments
= Qisr2app_
->query ();
513 p
->bytes
= (int)pHdr_
->dwUser
- bufferIndex_
514 + p
->fragsize
* p
->fragments
;
516 p
->bytes
= p
->fragsize
* p
->fragments
;
520 default_buf_info(p
, rate
, bits
, channels
);
524 void fhandler_dev_dsp::Audio_out::default_buf_info (audio_buf_info
*p
,
525 int rate
, int bits
, int channels
)
527 p
->fragstotal
= DEFAULT_BLOCKS
;
528 p
->fragsize
= blockSize (125, rate
, bits
, channels
);
529 p
->fragments
= p
->fragstotal
;
530 p
->bytes
= p
->fragsize
* p
->fragments
;
533 /* This is called on an interupt so use locking.. Note Qisr2app_
534 is used so we should wrap all references to it in locks. */
536 fhandler_dev_dsp::Audio_out::callback_sampledone (WAVEHDR
*pHdr
)
538 Qisr2app_
->send (pHdr
);
539 ReleaseSemaphore (fh
->get_select_sem (),
540 get_obj_handle_count (fh
->get_select_sem ()), NULL
);
544 fhandler_dev_dsp::Audio_out::waitforspace ()
547 MMRESULT rc
= WAVERR_STILLPLAYING
;
551 while (!Qisr2app_
->recv (&pHdr
))
553 if (fh
->is_nonblocking ())
558 switch (cygwait (fh
->get_select_sem (), 10))
561 if (!_my_tls
.call_signal_handler ())
568 pthread::static_cancel_self ();
576 /* Errors are ignored here. They will probbaly cause a failure
577 in the subsequent PrepareHeader */
578 rc
= waveOutUnprepareHeader (dev_
, pHdr
, sizeof (WAVEHDR
));
579 debug_printf ("%u = waveOutUnprepareHeader(%p)", rc
, pHdr
);
587 fhandler_dev_dsp::Audio_out::waitforallsent ()
589 while (Qisr2app_
->query () != fh
->fragstotal_
)
591 debug_printf ("%d blocks in Qisr2app", Qisr2app_
->query ());
597 // send the block described by pHdr_ and bufferIndex_ to wave device
599 fhandler_dev_dsp::Audio_out::sendcurrent ()
601 WAVEHDR
*pHdr
= pHdr_
;
603 debug_printf ("pHdr=%p bytes=%d", pHdr
, bufferIndex_
);
609 // Sample buffer conversion
610 (this->*convert_
) ((unsigned char *)pHdr
->lpData
, bufferIndex_
);
612 // Send internal buffer out to the soundcard
613 pHdr
->dwBufferLength
= bufferIndex_
;
614 rc
= waveOutPrepareHeader (dev_
, pHdr
, sizeof (WAVEHDR
));
615 debug_printf ("%u = waveOutPrepareHeader(%p)", rc
, pHdr
);
616 if (rc
== MMSYSERR_NOERROR
)
618 rc
= waveOutWrite (dev_
, pHdr
, sizeof (WAVEHDR
));
619 debug_printf ("%u = waveOutWrite(%p)", rc
, pHdr
);
621 if (rc
== MMSYSERR_NOERROR
)
624 /* FIXME: Should we return an error instead ?*/
625 pHdr
->dwFlags
= 0; /* avoid calling UnprepareHeader again */
626 Qisr2app_
->send (pHdr
);
630 //------------------------------------------------------------------------
633 waveOut_callback (HWAVEOUT hWave
, UINT msg
, DWORD_PTR instance
,
634 DWORD_PTR param1
, DWORD_PTR param2
)
638 fhandler_dev_dsp::Audio_out
*ptr
=
639 (fhandler_dev_dsp::Audio_out
*) instance
;
640 ptr
->callback_sampledone ((WAVEHDR
*) param1
);
644 //------------------------------------------------------------------------
645 // wav file detection..
654 unsigned short wFormatTag
;
655 unsigned short wChannels
;
656 unsigned int dwSamplesPerSec
;
657 unsigned int dwAvgBytesPerSec
;
658 unsigned short wBlockAlign
;
659 unsigned short wBitsPerSample
;
664 fhandler_dev_dsp::Audio_out::parsewav (const char * &pData
, int &nBytes
,
665 int dev_freq
, int dev_bits
, int dev_channels
)
668 const char *end
= pData
+ nBytes
;
672 /* Start with default values from the device handler */
675 channels_
= dev_channels
;
676 setconvert (bits_
== 8 ? AFMT_U8
: AFMT_S16_LE
);
678 // Check alignment first: A lot of the code below depends on it
679 if (((uintptr_t)pData
& 0x3) != 0)
681 if (!(pData
[0] == 'R' && pData
[1] == 'I'
682 && pData
[2] == 'F' && pData
[3] == 'F'))
684 if (!(pData
[8] == 'W' && pData
[9] == 'A'
685 && pData
[10] == 'V' && pData
[11] == 'E'))
688 len
= *(int *) &pData
[4];
692 while ((len
> 0) && (pDat
+ sizeof (wavchunk
) < end
))
693 { /* We recognize two kinds of wavchunk:
694 "fmt " for the PCM parameters (only PCM supported here)
695 "data" for the start of PCM data */
696 wavchunk
* pChunk
= (wavchunk
*) pDat
;
697 int blklen
= pChunk
-> len
;
698 if (pChunk
->id
[0] == 'f' && pChunk
->id
[1] == 'm'
699 && pChunk
->id
[2] == 't' && pChunk
->id
[3] == ' ')
701 wavformat
*format
= (wavformat
*) (pChunk
+ 1);
702 if ((char *) (format
+ 1) >= end
)
704 // We have found the parameter chunk
705 if (format
->wFormatTag
== 0x0001)
706 { // Micr*s*ft PCM; check if parameters work with our device
707 if (query (format
->dwSamplesPerSec
, format
->wBitsPerSample
,
709 { // return the parameters we found
710 freq_
= format
->dwSamplesPerSec
;
711 bits_
= format
->wBitsPerSample
;
712 channels_
= format
->wChannels
;
718 if (pChunk
->id
[0] == 'd' && pChunk
->id
[1] == 'a'
719 && pChunk
->id
[2] == 't' && pChunk
->id
[3] == 'a')
720 { // throw away all the header & not output it to the soundcard.
721 skip
+= sizeof (wavchunk
);
722 debug_printf ("Discard %d bytes wave header", skip
);
725 setconvert (bits_
== 8 ? AFMT_U8
: AFMT_S16_LE
);
729 pDat
+= blklen
+ sizeof (wavchunk
);
730 skip
+= blklen
+ sizeof (wavchunk
);
731 len
-= blklen
+ sizeof (wavchunk
);
736 /* ========================================================================
737 Buffering concept for Audio_in:
738 On the first read, we queue all blocks of our bigwavebuffer
739 for reception and start the wave-in device.
740 We manage queues of pointers to WAVEHDR
741 When a block has been filled, the callback puts the corresponding
742 WAVEHDR pointer into a queue.
743 The function read() blocks (polled, sigh) until at least one good buffer
744 has arrived, then the data is copied into the buffer provided to read().
745 After a buffer has been fully used by read(), it is queued again
746 to the wave-in device immediately.
747 The function read() iterates until all data requested has been
748 received, there is no way to interrupt it */
751 fhandler_dev_dsp::Audio_in::fork_fixup (HANDLE parent
)
754 It will be necessary to reset the queue, open the device
755 and create a lock when reading */
756 debug_printf ("parent=%p", parent
);
761 fhandler_dev_dsp::Audio_in::query (int rate
, int bits
, int channels
)
766 fillFormat (&format
, rate
, bits
, channels
);
767 rc
= waveInOpen (NULL
, WAVE_MAPPER
, &format
, 0L, 0L, WAVE_FORMAT_QUERY
);
768 debug_printf ("%u = waveInOpen(freq=%d bits=%d channels=%d)", rc
, rate
, bits
, channels
);
769 return (rc
== MMSYSERR_NOERROR
);
773 fhandler_dev_dsp::Audio_in::start (int rate
, int bits
, int channels
)
781 /* In case of fork bigwavebuffer may already exist */
783 bigwavebuffer_
= new char[fh
->fragstotal_
* fh
->fragsize_
];
788 fillFormat (&format
, rate
, bits
, channels
);
789 rc
= waveInOpen (&dev_
, WAVE_MAPPER
, &format
, (DWORD_PTR
) waveIn_callback
,
790 (DWORD_PTR
) this, CALLBACK_FUNCTION
);
791 debug_printf ("%u = waveInOpen(rate=%d bits=%d channels=%d)", rc
, rate
, bits
, channels
);
793 if (rc
== MMSYSERR_NOERROR
)
795 if (!init (fh
->fragsize_
))
798 return (rc
== MMSYSERR_NOERROR
);
802 fhandler_dev_dsp::Audio_in::stop ()
807 debug_printf ("dev_=%p", dev_
);
810 /* Note that waveInReset calls our callback for all incomplete buffers.
811 Since all the win32 wave functions appear to use a common lock,
812 we must not call into the wave API from the callback.
813 Otherwise we end up in a deadlock. */
814 rc
= waveInReset (dev_
);
815 debug_printf ("%u = waveInReset()", rc
);
817 while (Qisr2app_
->recv (&pHdr
))
819 rc
= waveInUnprepareHeader (dev_
, pHdr
, sizeof (WAVEHDR
));
820 debug_printf ("%u = waveInUnprepareHeader(%p)", rc
, pHdr
);
823 no_thread_exit_protect
for_now (true);
824 rc
= waveInClose (dev_
);
825 debug_printf ("%u = waveInClose()", rc
);
827 Qisr2app_
->dellock ();
832 fhandler_dev_dsp::Audio_in::queueblock (WAVEHDR
*pHdr
)
835 rc
= waveInPrepareHeader (dev_
, pHdr
, sizeof (WAVEHDR
));
836 debug_printf ("%u = waveInPrepareHeader(%p)", rc
, pHdr
);
837 if (rc
== MMSYSERR_NOERROR
)
839 rc
= waveInAddBuffer (dev_
, pHdr
, sizeof (WAVEHDR
));
840 debug_printf ("%u = waveInAddBuffer(%p)", rc
, pHdr
);
842 if (rc
== MMSYSERR_NOERROR
)
845 /* FIXME: Should the calling function return an error instead ?*/
846 pHdr
->dwFlags
= 0; /* avoid calling UnprepareHeader again */
847 pHdr
->dwBytesRecorded
= 0; /* no data will have been read */
848 Qisr2app_
->send (pHdr
);
853 fhandler_dev_dsp::Audio_in::init (unsigned blockSize
)
858 // try to queue all of our buffer for reception
860 for (i
= 0; i
< fh
->fragstotal_
; i
++)
862 wavehdr_
[i
].lpData
= &bigwavebuffer_
[i
* blockSize
];
863 wavehdr_
[i
].dwBufferLength
= blockSize
;
864 wavehdr_
[i
].dwFlags
= 0;
865 if (!queueblock (&wavehdr_
[i
]))
869 rc
= waveInStart (dev_
);
870 debug_printf ("%u = waveInStart(), queued=%d", rc
, i
);
871 return (rc
== MMSYSERR_NOERROR
);
875 fhandler_dev_dsp::Audio_in::read (char *pSampleData
, int &nBytes
)
877 int bytes_to_read
= nBytes
;
879 debug_printf ("pSampleData=%p nBytes=%d", pSampleData
, bytes_to_read
);
880 while (bytes_to_read
!= 0)
881 { // Block till next sound has been read
890 // Handle gathering our blocks into smaller or larger buffer
891 int sizeleft
= pHdr_
->dwBytesRecorded
- bufferIndex_
;
892 if (bytes_to_read
< sizeleft
)
893 { // The current buffer holds more data than requested
894 memcpy (pSampleData
, &pHdr_
->lpData
[bufferIndex_
], bytes_to_read
);
895 (this->*convert_
) ((unsigned char *)pSampleData
, bytes_to_read
);
896 nBytes
+= bytes_to_read
;
897 bufferIndex_
+= bytes_to_read
;
898 debug_printf ("got %d", bytes_to_read
);
899 break; // done; use remaining data in next call to read
902 { // not enough or exact amount in the current buffer
904 { // use up what we have
905 memcpy (pSampleData
, &pHdr_
->lpData
[bufferIndex_
], sizeleft
);
906 (this->*convert_
) ((unsigned char *)pSampleData
, sizeleft
);
908 bytes_to_read
-= sizeleft
;
909 pSampleData
+= sizeleft
;
910 debug_printf ("got %d", sizeleft
);
912 queueblock (pHdr_
); // re-queue this block to ISR
913 pHdr_
= NULL
; // need to wait for a new block
914 // if more samples are needed, we need a new block now
917 debug_printf ("end nBytes=%d", nBytes
);
922 fhandler_dev_dsp::Audio_in::waitfordata ()
929 while (!Qisr2app_
->recv (&pHdr
))
931 if (fh
->is_nonblocking ())
936 switch (cygwait (fh
->get_select_sem (), 10))
939 if (!_my_tls
.call_signal_handler ())
946 pthread::static_cancel_self ();
952 if (pHdr
->dwFlags
) /* Zero if queued following error in queueblock */
954 /* Errors are ignored here. They will probbaly cause a failure
955 in the subsequent PrepareHeader */
956 rc
= waveInUnprepareHeader (dev_
, pHdr
, sizeof (WAVEHDR
));
957 debug_printf ("%u = waveInUnprepareHeader(%p)", rc
, pHdr
);
964 void fhandler_dev_dsp::Audio_in::default_buf_info (audio_buf_info
*p
,
965 int rate
, int bits
, int channels
)
967 p
->fragstotal
= DEFAULT_BLOCKS
;
968 p
->fragsize
= blockSize (125, rate
, bits
, channels
);
974 fhandler_dev_dsp::Audio_in::buf_info (audio_buf_info
*p
,
975 int rate
, int bits
, int channels
)
979 p
->fragstotal
= fh
->fragstotal_
;
980 p
->fragsize
= fh
->fragsize_
;
981 p
->fragments
= Qisr2app_
->query ();
983 p
->bytes
= pHdr_
->dwBytesRecorded
- bufferIndex_
984 + p
->fragsize
* p
->fragments
;
986 p
->bytes
= p
->fragsize
* p
->fragments
;
990 default_buf_info(p
, rate
, bits
, channels
);
995 fhandler_dev_dsp::Audio_in::callback_blockfull (WAVEHDR
*pHdr
)
997 Qisr2app_
->send (pHdr
);
998 ReleaseSemaphore (fh
->get_select_sem (),
999 get_obj_handle_count (fh
->get_select_sem ()), NULL
);
1002 static void CALLBACK
1003 waveIn_callback (HWAVEIN hWave
, UINT msg
, DWORD_PTR instance
, DWORD_PTR param1
,
1006 if (msg
== WIM_DATA
)
1008 fhandler_dev_dsp::Audio_in
*ptr
=
1009 (fhandler_dev_dsp::Audio_in
*) instance
;
1010 ptr
->callback_blockfull ((WAVEHDR
*) param1
);
1015 /* ------------------------------------------------------------------------
1017 ------------------------------------------------------------------------ */
1018 fhandler_dev_dsp::fhandler_dev_dsp ():
1023 dev ().parse (FH_OSS_DSP
);
1027 fhandler_dev_dsp::write (const void *ptr
, size_t len
)
1029 return base ()->_write (ptr
, len
, this);
1033 fhandler_dev_dsp::read (void *ptr
, size_t& len
)
1035 base ()->_read (ptr
, len
, this);
1039 fhandler_dev_dsp::ioctl (unsigned int cmd
, void *buf
)
1041 return base ()->_ioctl (cmd
, buf
, this);
1045 fhandler_dev_dsp::fcntl (int cmd
, intptr_t arg
)
1047 return base ()->_fcntl (cmd
, arg
);
1051 fhandler_dev_dsp::fixup_after_fork (HANDLE parent
)
1053 base ()->_fixup_after_fork (parent
);
1057 fhandler_dev_dsp::fixup_after_exec ()
1059 base ()->_fixup_after_exec ();
1064 fhandler_dev_dsp::open (int flags
, mode_t mode
)
1066 int ret
= -1, err
= 0;
1067 UINT num_in
= 0, num_out
= 0;
1068 // Work out initial sample format & frequency, /dev/dsp defaults
1069 audioformat_
= AFMT_U8
;
1073 fragstotal_
= DEFAULT_BLOCKS
;
1074 fragment_has_been_set
= false;
1075 switch (flags
& O_ACCMODE
)
1078 if ((num_in
= waveInGetNumDevs ()) == 0)
1082 if ((num_out
= waveOutGetNumDevs ()) == 0)
1086 if ((num_in
= waveInGetNumDevs ()) == 0)
1096 ret
= open_null (flags
);
1098 select_sem
= CreateSemaphore (sec_none_cloexec (mode
), 0, INT32_MAX
, NULL
);
1100 debug_printf ("ACCMODE=%y audio_in=%d audio_out=%d, err=%d, ret=%d",
1101 flags
& O_ACCMODE
, num_in
, num_out
, err
, ret
);
1103 being_closed
= false;
1107 #define IS_WRITE() ((fh->get_flags() & O_ACCMODE) != O_RDONLY)
1108 #define IS_READ() ((fh->get_flags() & O_ACCMODE) != O_WRONLY)
1111 fhandler_dev_dsp::_write (const void *ptr
, size_t len
, fhandler_dev_dsp
*fh
)
1113 debug_printf ("ptr=%p len=%ld", ptr
, len
);
1115 const char *ptr_s
= static_cast <const char *> (ptr
);
1124 /* nothing to do */;
1125 else if (IS_WRITE ())
1127 if (fragment_has_been_set
)
1128 fragsize_
= max (Audio::blockSize (80.0 / fragstotal_
, audiofreq_
,
1129 audiobits_
, audiochannels_
),
1132 fragsize_
= Audio::blockSize (125, audiofreq_
, audiobits_
,
1134 debug_printf ("Allocating");
1135 if (!(audio_out_
= new Audio_out (this)))
1138 /* check for wave file & get parameters & skip header if possible. */
1140 if (audio_out_
->parsewav (ptr_s
, len_s
,
1141 audiofreq_
, audiobits_
, audiochannels_
))
1142 debug_printf ("=> ptr_s=%p len_s=%d", ptr_s
, len_s
);
1146 set_errno (EBADF
); // device was opened for read?
1150 /* Open audio device properly with callbacks.
1151 Private parameters were set in call to parsewav.
1152 This is a no-op when there are successive writes in the same process */
1153 if (!audio_out_
->start ())
1159 int written
= audio_out_
->write (ptr_s
, len_s
);
1162 if (len
- len_s
> 0)
1166 return len
- len_s
+ written
;
1170 fhandler_dev_dsp::_read (void *ptr
, size_t& len
, fhandler_dev_dsp
*fh
)
1172 debug_printf ("ptr=%p len=%ld", ptr
, len
);
1175 /* nothing to do */;
1176 else if (IS_READ ())
1178 if (!fragment_has_been_set
)
1179 fragsize_
= Audio::blockSize (125, audiofreq_
, audiobits_
,
1181 debug_printf ("Allocating");
1182 if (!(audio_in_
= new Audio_in (this)))
1187 audio_in_
->setconvert (audioformat_
);
1192 set_errno (EBADF
); // device was opened for write?
1196 /* Open audio device properly with callbacks.
1197 This is a noop when there are successive reads in the same process */
1198 if (!audio_in_
->start (audiofreq_
, audiobits_
, audiochannels_
))
1206 audio_in_
->read ((char *)ptr
, res
);
1211 fhandler_dev_dsp::close_audio_in ()
1222 fhandler_dev_dsp::close_audio_out (bool immediately
)
1226 audio_out_
->stop (immediately
);
1233 fhandler_dev_dsp::close ()
1235 debug_printf ("audio_in=%p audio_out=%p", audio_in_
, audio_out_
);
1236 being_closed
= true;
1239 ReleaseSemaphore (select_sem
, get_obj_handle_count (select_sem
), NULL
);
1240 CloseHandle (select_sem
);
1242 return fhandler_base::close ();
1246 fhandler_dev_dsp::_ioctl (unsigned int cmd
, void *buf
, fhandler_dev_dsp
*fh
)
1248 debug_printf ("audio_in=%p audio_out=%p", audio_in_
, audio_out_
);
1249 int *intbuf
= (int *) buf
;
1252 #define CASE(a) case a : debug_printf ("/dev/dsp: ioctl %s", #a);
1254 CASE (SNDCTL_DSP_RESET
)
1256 close_audio_out (true);
1260 CASE (SNDCTL_DSP_GETBLKSIZE
)
1261 if (fragment_has_been_set
)
1262 *intbuf
= max (Audio::blockSize (80.0 / fragstotal_
, audiofreq_
,
1263 audiobits_
, audiochannels_
),
1266 *intbuf
= Audio::blockSize (125, audiofreq_
, audiobits_
,
1270 CASE (SNDCTL_DSP_SETFMT
)
1276 *intbuf
= audioformat_
;
1292 if (nBits
&& IS_WRITE ())
1295 if (audio_out_
->query (audiofreq_
, nBits
, audiochannels_
))
1298 audioformat_
= *intbuf
;
1302 *intbuf
= audiobits_
;
1306 if (nBits
&& IS_READ ())
1309 if (audio_in_
->query (audiofreq_
, nBits
, audiochannels_
))
1312 audioformat_
= *intbuf
;
1316 *intbuf
= audiobits_
;
1323 CASE (SNDCTL_DSP_SPEED
)
1327 if (audio_out_
->query (*intbuf
, audiobits_
, audiochannels_
))
1328 audiofreq_
= *intbuf
;
1331 *intbuf
= audiofreq_
;
1338 if (audio_in_
->query (*intbuf
, audiobits_
, audiochannels_
))
1339 audiofreq_
= *intbuf
;
1342 *intbuf
= audiofreq_
;
1348 CASE (SNDCTL_DSP_STEREO
)
1350 int nChannels
= *intbuf
+ 1;
1351 int res
= _ioctl (SNDCTL_DSP_CHANNELS
, &nChannels
, fh
);
1352 *intbuf
= nChannels
- 1;
1356 CASE (SNDCTL_DSP_CHANNELS
)
1358 int nChannels
= *intbuf
;
1363 if (audio_out_
->query (audiofreq_
, audiobits_
, nChannels
))
1364 audiochannels_
= nChannels
;
1367 *intbuf
= audiochannels_
;
1374 if (audio_in_
->query (audiofreq_
, audiobits_
, nChannels
))
1375 audiochannels_
= nChannels
;
1378 *intbuf
= audiochannels_
;
1385 CASE (SNDCTL_DSP_GETOSPACE
)
1392 audio_buf_info
*p
= (audio_buf_info
*) buf
;
1394 audio_out_
->buf_info (p
, audiofreq_
, audiobits_
, audiochannels_
);
1395 else if (fragment_has_been_set
)
1397 p
->fragsize
= max (Audio::blockSize (80.0 / fragstotal_
,
1398 audiofreq_
, audiobits_
,
1401 p
->bytes
= p
->fragsize
* fragstotal_
;
1402 p
->fragstotal
= fragstotal_
;
1403 p
->fragments
= fragstotal_
;
1406 Audio_out::default_buf_info(p
, audiofreq_
, audiobits_
, audiochannels_
);
1407 debug_printf ("buf=%p frags=%d fragsize=%d bytes=%d",
1408 buf
, p
->fragments
, p
->fragsize
, p
->bytes
);
1412 CASE (SNDCTL_DSP_GETISPACE
)
1419 audio_buf_info
*p
= (audio_buf_info
*) buf
;
1421 audio_in_
->buf_info (p
, audiofreq_
, audiobits_
, audiochannels_
);
1422 else if (fragment_has_been_set
)
1425 p
->fragsize
= max (Audio::blockSize (80.0 / fragstotal_
,
1426 audiofreq_
, audiobits_
,
1429 p
->fragstotal
= fragstotal_
;
1433 Audio_in::default_buf_info(p
, audiofreq_
, audiobits_
, audiochannels_
);
1434 debug_printf ("buf=%p frags=%d fragsize=%d bytes=%d",
1435 buf
, p
->fragments
, p
->fragsize
, p
->bytes
);
1439 CASE (SNDCTL_DSP_SETFRAGMENT
)
1441 if (audio_out_
|| audio_in_
)
1442 return 0; /* Too late to set fragment. Ignore. */
1443 int *p
= (int *) buf
;
1444 fragstotal_
= min (*p
>> 16, MAX_BLOCKS
);
1445 fragsize_
= 1 << (*p
& 0xffff);
1446 if (fragstotal_
< 2)
1448 fragment_has_been_set
= true;
1452 CASE (SNDCTL_DSP_GETFMTS
)
1453 *intbuf
= AFMT_S16_LE
| AFMT_U8
; // only native formats returned here
1456 CASE (SNDCTL_DSP_GETCAPS
)
1457 *intbuf
= DSP_CAP_BATCH
| DSP_CAP_DUPLEX
;
1460 CASE (SNDCTL_DSP_POST
)
1462 audio_out_
->sendcurrent (); // force out last block whatever size..
1465 CASE (SNDCTL_DSP_SYNC
)
1468 audio_out_
->sendcurrent (); // force out last block whatever size..
1469 audio_out_
->waitforallsent (); // block till finished..
1474 return fhandler_base::ioctl (cmd
, buf
);
1482 fhandler_dev_dsp::_fcntl (int cmd
, intptr_t arg
)
1484 return fhandler_base::fcntl(cmd
, arg
);
1488 fhandler_dev_dsp::_fixup_after_fork (HANDLE parent
)
1489 { // called from new child process
1490 debug_printf ("audio_in=%p audio_out=%p",
1491 audio_in_
, audio_out_
);
1493 fhandler_base::fixup_after_fork (parent
);
1495 audio_in_
->fork_fixup (parent
);
1497 audio_out_
->fork_fixup (parent
);
1501 fhandler_dev_dsp::_fixup_after_exec ()
1503 debug_printf ("audio_in=%p audio_out=%p, close_on_exec %d",
1504 audio_in_
, audio_out_
, close_on_exec ());
1505 if (!close_on_exec ())
1513 fhandler_dev_dsp::_write_ready ()
1515 audio_buf_info info
;
1518 audio_out_
->buf_info (&info
, audiofreq_
, audiobits_
, audiochannels_
);
1519 return info
.bytes
> 0;
1526 fhandler_dev_dsp::_read_ready ()
1528 audio_buf_info info
;
1531 audio_in_
->buf_info (&info
, audiofreq_
, audiobits_
, audiochannels_
);
1532 return info
.bytes
> 0;
1539 fhandler_dev_dsp::write_ready ()
1541 return base ()->_write_ready ();
1545 fhandler_dev_dsp::read_ready ()
1547 return base ()->_read_ready ();
1551 fhandler_dev_dsp::open_setup (int flags
)
1553 set_flags ((flags
& ~O_TEXT
) | O_BINARY
);
1554 return fhandler_base::open_setup (flags
);