From owner-freebsd-multimedia@FreeBSD.ORG Sat Feb 7 15:20:18 2015 Return-Path: Delivered-To: freebsd-multimedia@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 7079FC36; Sat, 7 Feb 2015 15:20:18 +0000 (UTC) Received: from mail.turbocat.net (heidi.turbocat.net [88.198.202.214]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 11A6E26F; Sat, 7 Feb 2015 15:20:14 +0000 (UTC) Received: from laptop015.home.selasky.org (cm-176.74.213.204.customer.telag.net [176.74.213.204]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.turbocat.net (Postfix) with ESMTPSA id C156F1FE023; Sat, 7 Feb 2015 16:20:11 +0100 (CET) Message-ID: <54D62D5D.2000201@selasky.org> Date: Sat, 07 Feb 2015 16:21:01 +0100 From: Hans Petter Selasky User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: freebsd-usb@freebsd.org, freebsd-multimedia@FreeBSD.org Subject: USB audio patch Content-Type: multipart/mixed; boundary="------------080502000008090701010708" X-BeenThere: freebsd-multimedia@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Multimedia discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Feb 2015 15:20:18 -0000 This is a multi-part message in MIME format. --------------080502000008090701010708 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Hi, If you have a USB audio device which uses the feedback endpoint, where the sample rate is not locked to the USB, you may want to try the attached patch. I will test it a bit more and then it will hit the tree next week. The basic of the change is to reduce the number of sample rate adjustments. Some devices only update the sample rate very slowly, and the current USB audio driver is polling very fast, so the algorithm simply becomes unreliable with some kinds of USB audio devices. --HPS --------------080502000008090701010708 Content-Type: text/x-patch; name="uaudio.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="uaudio.patch" Index: sys/dev/sound/usb/uaudio.c =================================================================== --- sys/dev/sound/usb/uaudio.c (revision 278206) +++ sys/dev/sound/usb/uaudio.c (working copy) @@ -111,6 +111,7 @@ &uaudio_default_channels, 0, "uaudio default sample channels"); #endif +#define UAUDIO_IRQS (8000 / UAUDIO_NFRAMES) /* interrupts per second */ #define UAUDIO_NFRAMES 64 /* must be factor of 8 due HS-USB */ #define UAUDIO_NCHANBUFS 2 /* number of outstanding request */ #define UAUDIO_RECURSE_LIMIT 255 /* rounds */ @@ -189,7 +190,6 @@ uint8_t iface_index; uint8_t iface_alt_index; uint8_t channels; - uint8_t enable_sync; }; struct uaudio_chan { @@ -226,11 +226,10 @@ #define CHAN_OP_STOP 2 #define CHAN_OP_DRAIN 3 - uint8_t last_sync_time; - uint8_t last_sync_state; -#define UAUDIO_SYNC_NONE 0 -#define UAUDIO_SYNC_MORE 1 -#define UAUDIO_SYNC_LESS 2 + /* USB audio feedback endpoint state */ + int16_t last_sync_time; + int16_t last_sync_constant; /* sample rate adjustment in Hz */ + int16_t last_sync_remainder; }; #define UMIDI_EMB_JACK_MAX 16 /* units */ @@ -1799,14 +1798,6 @@ chan_alt->iface_index = curidx; chan_alt->iface_alt_index = alt_index; - if (UEP_HAS_SYNCADDR(ed1) && ed1->bSynchAddress != 0) { - DPRINTF("Sync endpoint will be used, if present\n"); - chan_alt->enable_sync = 1; - } else { - DPRINTF("Sync endpoint will not be used\n"); - chan_alt->enable_sync = 0; - } - usbd_set_parent_iface(sc->sc_udev, curidx, sc->sc_mixer_iface_index); @@ -2028,17 +2019,21 @@ while (temp > (sample_rate + (sample_rate / 2))) temp /= 2; - /* compare */ - DPRINTF("Comparing %d < %d\n", (int)temp, (int)sample_rate); - if (temp == sample_rate) - ch->last_sync_state = UAUDIO_SYNC_NONE; - else if (temp > sample_rate) - ch->last_sync_state = UAUDIO_SYNC_MORE; - else - ch->last_sync_state = UAUDIO_SYNC_LESS; + /* Update sync constant */ + ch->last_sync_constant += (temp - sample_rate); + + /* + * Range check sync constant. We cannot change the + * number of samples per second by more than the value + * defined by "UAUDIO_IRQS": + */ + if (ch->last_sync_constant > UAUDIO_IRQS) + ch->last_sync_constant = UAUDIO_IRQS; + else if (ch->last_sync_constant < -UAUDIO_IRQS) + ch->last_sync_constant = -UAUDIO_IRQS; break; case USB_ST_SETUP: @@ -2082,10 +2077,10 @@ } chn_intr(ch->pcm_ch); - /* start SYNC transfer, if any */ - if (ch->usb_alt[ch->cur_alt].enable_sync != 0) { - if ((ch->last_sync_time++ & 7) == 0) - usbd_transfer_start(ch->xfer[UAUDIO_NCHANBUFS]); + /* start the SYNC transfer one time per second, if any */ + if (++(ch->last_sync_time) >= UAUDIO_IRQS) { + ch->last_sync_time = 0; + usbd_transfer_start(ch->xfer[UAUDIO_NCHANBUFS]); } case USB_ST_SETUP: @@ -2120,21 +2115,22 @@ } if (n == (blockcount - 1)) { - switch (ch->last_sync_state) { - case UAUDIO_SYNC_MORE: + /* + * Update sync remainder and check if + * we should transmit more or less + * data: + */ + ch->last_sync_remainder += ch->last_sync_constant; + if (ch->last_sync_remainder >= UAUDIO_IRQS) { + ch->last_sync_remainder -= UAUDIO_IRQS; DPRINTFN(6, "sending one sample more\n"); if ((frame_len + sample_size) <= mfl) frame_len += sample_size; - ch->last_sync_state = UAUDIO_SYNC_NONE; - break; - case UAUDIO_SYNC_LESS: + } else if (ch->last_sync_remainder <= -UAUDIO_IRQS) { + ch->last_sync_remainder += UAUDIO_IRQS; DPRINTFN(6, "sending one sample less\n"); if (frame_len >= sample_size) frame_len -= sample_size; - ch->last_sync_state = UAUDIO_SYNC_NONE; - break; - default: - break; } } --------------080502000008090701010708--