From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7868) id BD9303858D28; Tue, 31 Jan 2023 11:36:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BD9303858D28 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1675164979; bh=8ptLjFtZBY3nAgudo9A78hj5JoRj420ZnXAfvvi2BFM=; h=From:To:Subject:Date:From; b=kPePxu+Xr+AbNXkeJqamwQoMy4hi+Nl7qJfk4EWrEwXM3PPGM8PoL6LVeUthmuAK2 pF/QTyQ74Eeqd7e/PUrzM768eGQJMA62AR3a9SDHzge9LO+dO6yrjiTF2hXz0f1iug cXtnNXPvvBAPjL8+8RhgKWKPxpHrRkVaVJjUYLZs= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Takashi Yano To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: dsp: Implement SNDCTL_DSP_SETFRAGMENT ioctl(). X-Act-Checkin: newlib-cygwin X-Git-Author: Takashi Yano X-Git-Refname: refs/heads/master X-Git-Oldrev: 4b157b44cad099c375801453dc245da660f0cb85 X-Git-Newrev: 3a4c740f59c03b4c8346fa0ee8599b1c0582ae96 Message-Id: <20230131113619.BD9303858D28@sourceware.org> Date: Tue, 31 Jan 2023 11:36:19 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D3a4c740f59c= 03b4c8346fa0ee8599b1c0582ae96 commit 3a4c740f59c03b4c8346fa0ee8599b1c0582ae96 Author: Takashi Yano Date: Sat Jan 28 13:07:32 2023 +0900 Cygwin: dsp: Implement SNDCTL_DSP_SETFRAGMENT ioctl(). =20 Previously, SNDCTL_DSP_SETFRAGMENT was just a fake. In this patch, it has been implemented to allow latency control in some apps. =20 Reviewed-by: Corinna Vinschen Signed-off-by: Takashi Yano Diff: --- winsup/cygwin/fhandler/dsp.cc | 78 ++++++++++++++++-------------= ---- winsup/cygwin/local_includes/fhandler.h | 3 ++ 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/winsup/cygwin/fhandler/dsp.cc b/winsup/cygwin/fhandler/dsp.cc index cfbf6bec7..dd1aac8e2 100644 --- a/winsup/cygwin/fhandler/dsp.cc +++ b/winsup/cygwin/fhandler/dsp.cc @@ -46,6 +46,8 @@ details. */ children. They only inherit the settings from the parent. */ =20 +enum { DEFAULT_BLOCKS =3D 12, MAX_BLOCKS =3D 256 }; + class fhandler_dev_dsp::Audio { // This class contains functionality common to Audio_in and Audio_out public: @@ -67,7 +69,6 @@ class fhandler_dev_dsp::Audio void (fhandler_dev_dsp::Audio::*convert_) (unsigned char *buffer, int size_bytes); =20 - enum { MAX_BLOCKS =3D 12 }; int bufferIndex_; // offset into pHdr_->lpData WAVEHDR *pHdr_; // data to be filled by write WAVEHDR wavehdr_[MAX_BLOCKS]; @@ -126,7 +127,6 @@ class fhandler_dev_dsp::Audio_out: public Audio bool waitforspace (); bool sendcurrent (); =20 - enum { MAX_BLOCKS =3D 12 }; HWAVEOUT dev_; // The wave device /* Private copies of audiofreq_, audiobits_, audiochannels_, possibly set from wave file */ @@ -235,9 +235,9 @@ fhandler_dev_dsp::Audio::queue::query () fhandler_dev_dsp::Audio::Audio (fhandler_dev_dsp *my_fh) { bigwavebuffer_ =3D NULL; - Qisr2app_ =3D new queue (MAX_BLOCKS); - convert_ =3D &fhandler_dev_dsp::Audio::convert_none; fh =3D my_fh; + Qisr2app_ =3D new queue (fh->fragstotal_); + convert_ =3D &fhandler_dev_dsp::Audio::convert_none; } =20 fhandler_dev_dsp::Audio::~Audio () @@ -389,14 +389,13 @@ fhandler_dev_dsp::Audio_out::start () { WAVEFORMATEX format; MMRESULT rc; - unsigned bSize =3D blockSize (freq_, bits_, channels_); =20 if (dev_) return true; =20 /* In case of fork bigwavebuffer may already exist */ if (!bigwavebuffer_) - bigwavebuffer_ =3D new char[MAX_BLOCKS * bSize]; + bigwavebuffer_ =3D new char[fh->fragstotal_ * fh->fragsize_]; =20 if (!isvalid ()) return false; @@ -405,7 +404,7 @@ fhandler_dev_dsp::Audio_out::start () rc =3D waveOutOpen (&dev_, WAVE_MAPPER, &format, (DWORD_PTR) waveOut_cal= lback, (DWORD_PTR) this, CALLBACK_FUNCTION); if (rc =3D=3D MMSYSERR_NOERROR) - init (bSize); + init (fh->fragsize_); =20 debug_printf ("%u =3D waveOutOpen(freq=3D%d bits=3D%d channels=3D%d)", r= c, freq_, bits_, channels_); =20 @@ -450,7 +449,7 @@ fhandler_dev_dsp::Audio_out::init (unsigned blockSize) =20 // internally queue all of our buffer for later use by write Qisr2app_->reset (); - for (i =3D 0; i < MAX_BLOCKS; i++) + for (i =3D 0; i < fh->fragstotal_; i++) { wavehdr_[i].lpData =3D &bigwavebuffer_[i * blockSize]; wavehdr_[i].dwUser =3D (int) blockSize; @@ -505,8 +504,8 @@ fhandler_dev_dsp::Audio_out::buf_info (audio_buf_info *= p, { /* If the device is running we use the internal values, possibly set from the wave file. */ - p->fragstotal =3D MAX_BLOCKS; - p->fragsize =3D blockSize (freq_, bits_, channels_); + p->fragstotal =3D fh->fragstotal_; + p->fragsize =3D fh->fragsize_; p->fragments =3D Qisr2app_->query (); if (pHdr_ !=3D NULL) p->bytes =3D (int)pHdr_->dwUser - bufferIndex_ @@ -523,10 +522,10 @@ fhandler_dev_dsp::Audio_out::buf_info (audio_buf_info= *p, void fhandler_dev_dsp::Audio_out::default_buf_info (audio_buf_info *p, int rate, int bits, int ch= annels) { - p->fragstotal =3D MAX_BLOCKS; - p->fragsize =3D blockSize (rate, bits, channels); - p->fragments =3D MAX_BLOCKS; - p->bytes =3D p->fragsize * p->fragments; + p->fragstotal =3D DEFAULT_BLOCKS; + p->fragsize =3D blockSize (rate, bits, channels); + p->fragments =3D p->fragstotal; + p->bytes =3D p->fragsize * p->fragments; } =20 /* This is called on an interupt so use locking.. Note Qisr2app_ @@ -552,8 +551,8 @@ fhandler_dev_dsp::Audio_out::waitforspace () set_errno (EAGAIN); return false; } - debug_printf ("100ms"); - switch (cygwait (100)) + debug_printf ("1ms"); + switch (cygwait (1)) { case WAIT_SIGNALED: if (!_my_tls.call_signal_handler ()) @@ -584,7 +583,7 @@ fhandler_dev_dsp::Audio_out::waitforspace () void fhandler_dev_dsp::Audio_out::waitforallsent () { - while (Qisr2app_->query () !=3D MAX_BLOCKS) + while (Qisr2app_->query () !=3D fh->fragstotal_) { debug_printf ("%d blocks in Qisr2app", Qisr2app_->query ()); Sleep (100); @@ -771,14 +770,13 @@ fhandler_dev_dsp::Audio_in::start (int rate, int bits= , int channels) { WAVEFORMATEX format; MMRESULT rc; - unsigned bSize =3D blockSize (rate, bits, channels); =20 if (dev_) return true; =20 /* In case of fork bigwavebuffer may already exist */ if (!bigwavebuffer_) - bigwavebuffer_ =3D new char[MAX_BLOCKS * bSize]; + bigwavebuffer_ =3D new char[fh->fragstotal_ * fh->fragsize_]; =20 if (!isvalid ()) return false; @@ -790,7 +788,7 @@ fhandler_dev_dsp::Audio_in::start (int rate, int bits, = int channels) =20 if (rc =3D=3D MMSYSERR_NOERROR) { - if (!init (bSize)) + if (!init (fh->fragsize_)) return false; } return (rc =3D=3D MMSYSERR_NOERROR); @@ -855,7 +853,7 @@ fhandler_dev_dsp::Audio_in::init (unsigned blockSize) =20 // try to queue all of our buffer for reception Qisr2app_->reset (); - for (i =3D 0; i < MAX_BLOCKS; i++) + for (i =3D 0; i < fh->fragstotal_; i++) { wavehdr_[i].lpData =3D &bigwavebuffer_[i * blockSize]; wavehdr_[i].dwBufferLength =3D blockSize; @@ -963,7 +961,7 @@ fhandler_dev_dsp::Audio_in::waitfordata () void fhandler_dev_dsp::Audio_in::default_buf_info (audio_buf_info *p, int rate, int bits, int ch= annels) { - p->fragstotal =3D MAX_BLOCKS; + p->fragstotal =3D DEFAULT_BLOCKS; p->fragsize =3D blockSize (rate, bits, channels); p->fragments =3D 0; p->bytes =3D 0; @@ -975,8 +973,8 @@ fhandler_dev_dsp::Audio_in::buf_info (audio_buf_info *p, { if (dev_) { - p->fragstotal =3D MAX_BLOCKS; - p->fragsize =3D blockSize (rate, bits, channels); + p->fragstotal =3D fh->fragstotal_; + p->fragsize =3D fh->fragsize_; p->fragments =3D Qisr2app_->query (); if (pHdr_ !=3D NULL) p->bytes =3D pHdr_->dwBytesRecorded - bufferIndex_ @@ -1068,6 +1066,8 @@ fhandler_dev_dsp::open (int flags, mode_t) audiofreq_ =3D 8000; audiobits_ =3D 8; audiochannels_ =3D 1; + fragstotal_ =3D DEFAULT_BLOCKS; + fragment_has_been_set =3D false; switch (flags & O_ACCMODE) { case O_RDWR: @@ -1118,6 +1118,8 @@ fhandler_dev_dsp::_write (const void *ptr, size_t len) /* nothing to do */; else if (IS_WRITE ()) { + if (!fragment_has_been_set) + fragsize_ =3D Audio::blockSize (audiofreq_, audiobits_, audiochannels_); debug_printf ("Allocating"); if (!(audio_out_ =3D new Audio_out (this))) return -1; @@ -1162,6 +1164,8 @@ fhandler_dev_dsp::_read (void *ptr, size_t& len) /* nothing to do */; else if (IS_READ ()) { + if (!fragment_has_been_set) + fragsize_ =3D Audio::blockSize (audiofreq_, audiobits_, audiochannels_); debug_printf ("Allocating"); if (!(audio_in_ =3D new Audio_in (this))) { @@ -1237,19 +1241,9 @@ fhandler_dev_dsp::_ioctl (unsigned int cmd, void *bu= f) break; =20 CASE (SNDCTL_DSP_GETBLKSIZE) - /* This is valid even if audio_X is NULL */ - if (IS_WRITE ()) - { - *intbuf =3D audio_out_->blockSize (audiofreq_, - audiobits_, - audiochannels_); - } - else - { // I am very sure that IS_READ is valid - *intbuf =3D audio_in_->blockSize (audiofreq_, - audiobits_, - audiochannels_); - } + if (!fragment_has_been_set) + fragsize_ =3D Audio::blockSize (audiofreq_, audiobits_, audiochannels_); + *intbuf =3D fragsize_; return 0; =20 CASE (SNDCTL_DSP_SETFMT) @@ -1404,9 +1398,15 @@ fhandler_dev_dsp::_ioctl (unsigned int cmd, void *bu= f) } =20 CASE (SNDCTL_DSP_SETFRAGMENT) - // Fake!! esound & mikmod require this on non PowerPC platforms. - // + { + if (audio_out_ || audio_in_) + return 0; /* Too late to set fragment. Ignore. */ + int *p =3D (int *) buf; + fragstotal_ =3D min (*p >> 16, MAX_BLOCKS); + fragsize_ =3D 1 << (*p & 0xffff); + fragment_has_been_set =3D true; return 0; + } =20 CASE (SNDCTL_DSP_GETFMTS) *intbuf =3D AFMT_S16_LE | AFMT_U8; // only native formats returned here diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_= includes/fhandler.h index f3dd1b5a4..085a2a10d 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -2763,6 +2763,9 @@ class fhandler_dev_dsp: public fhandler_base Audio_out *audio_out_; Audio_in *audio_in_; bool being_closed; + bool fragment_has_been_set; + int fragstotal_; + int fragsize_; public: fhandler_dev_dsp (); fhandler_dev_dsp *base () const {return (fhandler_dev_dsp *)archetype;}