mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-06 21:25:03 -05:00
Add feedback not based on samples used, but on buffers filled - idea
being we can do "PID" (someone who has actually implemented Real PID
could probably rewrite the calculation) based on how many buffers
we have filled versus the ideal buffer filled level (16).
Feedback is based on a historical average of the last two feedback
intervals.
This feedback math is done as fixed-point math to keep floats out of core. Note that a couple division operations needed to be strategically staged to avoid overflow or truncation.
Floats are still used for debug screen printout.
Also fixed a typo in the definition of usb_audio_control_request()
Host:
Linux: works
MacOS: works
Windows: Feedback does not work! It appears that Windows may not
support asynchronous devices at all. Playback may "work",
but results will vary as the number of buffers filled will
drift over time.
Change-Id: I027feb16705e6e46c1144b1d08920b53de42cb26
270 lines
10 KiB
C
270 lines
10 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id: $
|
|
*
|
|
* Copyright (C) 2010 by Amaury Pouly
|
|
*
|
|
* All files in this archive are subject to the GNU General Public License.
|
|
* See the file COPYING in the source tree root for full license agreement.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
/* Parts of this file are based on Frank Gevaerts work and on audio.h from linux */
|
|
|
|
/* NOTE
|
|
*
|
|
* This is USBAudio 1.0. USBAudio 2.0 is notably _not backwards compatible!_
|
|
* USBAudio 1.0 over _USB_ 2.0 is perfectly valid!
|
|
*
|
|
* Relevant specifications are USB 2.0 and USB Audio Class 1.0.
|
|
*/
|
|
|
|
#ifndef USB_AUDIO_DEF_H
|
|
#define USB_AUDIO_DEF_H
|
|
|
|
#include "usb_ch9.h"
|
|
|
|
#define USB_SUBCLASS_AUDIO_CONTROL 1
|
|
#define USB_SUBCLASS_AUDIO_STREAMING 2
|
|
|
|
#define USB_AC_HEADER 1
|
|
#define USB_AC_INPUT_TERMINAL 2
|
|
#define USB_AC_OUTPUT_TERMINAL 3
|
|
#define USB_AC_MIXER_UNIT 4
|
|
#define USB_AC_SELECTOR_UNIT 5
|
|
#define USB_AC_FEATURE_UNIT 6
|
|
#define USB_AC_PROCESSING_UNIT 8
|
|
#define USB_AC_EXTENSION_UNIT 9
|
|
|
|
#define USB_AS_GENERAL 1
|
|
#define USB_AS_FORMAT_TYPE 2
|
|
|
|
#define USB_AC_CHANNEL_LEFT_FRONT 0x1
|
|
#define USB_AC_CHANNEL_RIGHT_FRONT 0x2
|
|
|
|
#define USB_AC_CHANNELS_LEFT_RIGHT_FRONT (USB_AC_CHANNEL_LEFT_FRONT | USB_AC_CHANNEL_RIGHT_FRONT)
|
|
|
|
/* usb audio data structures */
|
|
struct usb_ac_header {
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
|
|
uint8_t bDescriptorSubType; /* USB_AC_HEADER */
|
|
uint16_t bcdADC;
|
|
uint16_t wTotalLength;
|
|
uint8_t bInCollection;
|
|
uint8_t baInterfaceNr[];
|
|
} __attribute__ ((packed));
|
|
|
|
#define USB_AC_SIZEOF_HEADER(n) (8 + (n))
|
|
|
|
#define USB_AC_TERMINAL_UNDEFINED 0x100
|
|
#define USB_AC_TERMINAL_STREAMING 0x101
|
|
#define USB_AC_TERMINAL_VENDOR_SPEC 0x1ff
|
|
|
|
#define USB_AC_EXT_TERMINAL_UNDEFINED 0x600
|
|
#define USB_AC_EXT_TERMINAL_ANALOG 0x601
|
|
#define USB_AC_EXT_TERMINAL_DIGITAL 0x602
|
|
#define USB_AC_EXT_TERMINAL_LINE 0x603
|
|
#define USB_AC_EXT_TERMINAL_LEGACY 0x604
|
|
#define USB_AC_EXT_TERMINAL_SPDIF 0x605
|
|
#define USB_AC_EXT_TERMINAL_1394_DA 0x606
|
|
#define USB_AC_EXT_TERMINAL_1394_DV 0x607
|
|
|
|
#define USB_AC_EMB_MINIDISK 0x706
|
|
#define USB_AC_EMB_RADIO_RECV 0x710
|
|
|
|
#define USB_AC_INPUT_TERMINAL_UNDEFINED 0x200
|
|
#define USB_AC_INPUT_TERMINAL_MICROPHONE 0x201
|
|
#define USB_AC_INPUT_TERMINAL_DESKTOP_MICROPHONE 0x202
|
|
#define USB_AC_INPUT_TERMINAL_PERSONAL_MICROPHONE 0x203
|
|
#define USB_AC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE 0x204
|
|
#define USB_AC_INPUT_TERMINAL_MICROPHONE_ARRAY 0x205
|
|
#define USB_AC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY 0x206
|
|
|
|
struct usb_ac_input_terminal {
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
|
|
uint8_t bDescriptorSubType; /* USB_AC_INPUT_TERMINAL */
|
|
uint8_t bTerminalId;
|
|
uint16_t wTerminalType; /* USB_AC_INPUT_TERMINAL_* */
|
|
uint8_t bAssocTerminal;
|
|
uint8_t bNrChannels;
|
|
uint16_t wChannelConfig;
|
|
uint8_t iChannelNames;
|
|
uint8_t iTerminal;
|
|
} __attribute__ ((packed));
|
|
|
|
#define USB_AC_OUTPUT_TERMINAL_UNDEFINED 0x300
|
|
#define USB_AC_OUTPUT_TERMINAL_SPEAKER 0x301
|
|
#define USB_AC_OUTPUT_TERMINAL_HEADPHONES 0x302
|
|
#define USB_AC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303
|
|
#define USB_AC_OUTPUT_TERMINAL_DESKTOP_SPEAKER 0x304
|
|
#define USB_AC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305
|
|
#define USB_AC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306
|
|
#define USB_AC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307
|
|
|
|
struct usb_ac_output_terminal {
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
|
|
uint8_t bDescriptorSubType; /* USB_AC_OUTPUT_TERMINAL */
|
|
uint8_t bTerminalId;
|
|
uint16_t wTerminalType; /* USB_AC_OUTPUT_TERMINAL_* */
|
|
uint8_t bAssocTerminal;
|
|
uint8_t bSourceId;
|
|
uint8_t iTerminal;
|
|
} __attribute__ ((packed));
|
|
|
|
#define USB_AC_FU_CONTROL_UNDEFINED 0x00
|
|
#define USB_AC_MUTE_CONTROL 0x01
|
|
#define USB_AC_VOLUME_CONTROL 0x02
|
|
#define USB_AC_BASS_CONTROL 0x03
|
|
#define USB_AC_MID_CONTROL 0x04
|
|
#define USB_AC_TREBLE_CONTROL 0x05
|
|
#define USB_AC_EQUALIZER_CONTROL 0x06
|
|
#define USB_AC_AUTO_GAIN_CONTROL 0x07
|
|
#define USB_AC_DELAY_CONTROL 0x08
|
|
#define USB_AC_BASS_BOOST_CONTROL 0x09
|
|
#define USB_AC_LOUDNESS_CONTROL 0x0a
|
|
|
|
#define USB_AC_FU_MUTE (1 << (USB_AC_MUTE_CONTROL - 1))
|
|
#define USB_AC_FU_VOLUME (1 << (USB_AC_VOLUME_CONTROL - 1))
|
|
#define USB_AC_FU_BASS (1 << (USB_AC_BASS_CONTROL - 1))
|
|
#define USB_AC_FU_MID (1 << (USB_AC_MID_CONTROL - 1))
|
|
#define USB_AC_FU_TREBLE (1 << (USB_AC_TREBLE_CONTROL - 1))
|
|
#define USB_AC_FU_EQUILIZER (1 << (USB_AC_EQUALIZER_CONTROL - 1))
|
|
#define USB_AC_FU_AUTO_GAIN (1 << (USB_AC_AUTO_GAIN_CONTROL - 1))
|
|
#define USB_AC_FU_DELAY (1 << (USB_AC_DELAY_CONTROL - 1))
|
|
#define USB_AC_FU_BASS_BOOST (1 << (USB_AC_BASS_BOOST_CONTROL - 1))
|
|
#define USB_AC_FU_LOUDNESS (1 << (USB_AC_LOUDNESS_CONTROL - 1))
|
|
|
|
#define DEFINE_USB_AC_FEATURE_UNIT(n,ch) \
|
|
struct usb_ac_feature_unit_##n##_##ch { \
|
|
uint8_t bLength; \
|
|
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */ \
|
|
uint8_t bDescriptorSubType; /* USB_AC_FEATURE_UNIT */ \
|
|
uint8_t bUnitId; \
|
|
uint8_t bSourceId; \
|
|
uint8_t bControlSize; \
|
|
uint##n##_t bmaControls[ch + 1]; /* FU_* ORed*/ \
|
|
uint8_t iFeature; \
|
|
} __attribute__ ((packed));
|
|
|
|
#define USB_AC_SET_REQ 0x00
|
|
#define USB_AC_GET_REQ 0x80
|
|
|
|
#define USB_AC_CUR_REQ 0x1
|
|
#define USB_AC_MIN_REQ 0x2
|
|
#define USB_AC_MAX_REQ 0x3
|
|
#define USB_AC_RES_REQ 0x4
|
|
#define USB_AC_MEM_REQ 0x5
|
|
|
|
#define USB_AC_SET_CUR (USB_AC_SET_REQ | USB_AC_CUR_REQ)
|
|
#define USB_AC_GET_CUR (USB_AC_GET_REQ | USB_AC_CUR_REQ)
|
|
#define USB_AC_SET_MIN (USB_AC_SET_REQ | USB_AC_MIN_REQ)
|
|
#define USB_AC_GET_MIN (USB_AC_GET_REQ | USB_AC_MIN_REQ)
|
|
#define USB_AC_SET_MAX (USB_AC_SET_REQ | USB_AC_MAX_REQ)
|
|
#define USB_AC_GET_MAX (USB_AC_GET_REQ | USB_AC_MAX_REQ)
|
|
#define USB_AC_SET_RES (USB_AC_SET_REQ | USB_AC_RES_REQ)
|
|
#define USB_AC_GET_RES (USB_AC_GET_REQ | USB_AC_RES_REQ)
|
|
#define USB_AC_SET_MEM (USB_AC_SET_REQ | USB_AC_MEM_REQ)
|
|
#define USB_AC_GET_MEM (USB_AC_GET_REQ | USB_AC_MEM_REQ)
|
|
#define USB_AC_GET_STAT 0xff
|
|
|
|
#define USB_AS_FORMAT_TYPE_UNDEFINED 0x0
|
|
#define USB_AS_FORMAT_TYPE_I 0x1
|
|
#define USB_AS_FORMAT_TYPE_II 0x2
|
|
#define USB_AS_FORMAT_TYPE_III 0x3
|
|
|
|
struct usb_as_interface {
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
|
|
uint8_t bDescriptorSubType; /* USB_AS_GENERAL */
|
|
uint8_t bTerminalLink;
|
|
uint8_t bDelay;
|
|
uint16_t wFormatTag;
|
|
} __attribute__ ((packed));
|
|
|
|
#define USB_AS_EP_GENERAL 0x01
|
|
|
|
#define USB_AS_EP_CS_SAMPLING_FREQ_CTL 0x01
|
|
#define USB_AS_EP_CS_PITCH_CTL 0x02
|
|
|
|
// Standard* AudioStreaming Isochronous Audio Data Endpoint Descriptor
|
|
//
|
|
// *Note, per usbaudio 1.0 this is explititly identical
|
|
// to a standard endpoint descriptor but with extra information
|
|
struct usb_as_iso_audio_endpoint {
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType;
|
|
|
|
uint8_t bEndpointAddress;
|
|
uint8_t bmAttributes;
|
|
uint16_t wMaxPacketSize;
|
|
uint8_t bInterval; /* MUST be set to 1 (full speed), +3 for high-speed? */
|
|
uint8_t bRefresh; /* USB Audio Class 1.0 specific: set to 0 */
|
|
uint8_t bSynchAddress; /* USB Audio Class 1.0 specific: used to identify synch ep */
|
|
} __attribute__ ((packed));
|
|
|
|
// Class-Specific AudioStreaming Isochronous Audio* (Control) Data Endpoint Descriptor
|
|
//
|
|
// *The name is a bit misleading, this is for _control_ of audio,
|
|
// such as sampling frequency or pitch.
|
|
struct usb_as_iso_ctrldata_endpoint {
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType; /* USB_DT_CS_ENDPOINT */
|
|
uint8_t bDescriptorSubType; /* USB_AS_EP_GENERAL */
|
|
uint8_t bmAttributes;
|
|
uint8_t bLockDelayUnits; /* USB Audio Class 1.0 specific */
|
|
uint16_t wLockDelay; /* USB Audio Class 1.0 specific */
|
|
} __attribute__ ((packed));
|
|
|
|
// Standard* AudioStreaming Isochronous Synch (Feedback) Endpoint Descriptor
|
|
//
|
|
// *Note, per usbaudio 1.0 this is explititly identical
|
|
// to a standard endpoint descriptor but with extra information
|
|
struct usb_as_iso_synch_endpoint {
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType; /* USB_DT_CS_ENDPOINT */
|
|
|
|
uint8_t bEndpointAddress; /* D7: direction (0 = source, 1 = sink)
|
|
* D6..4: Zeros
|
|
* D3..0: EP Number */
|
|
uint8_t bmAttributes; /* USBAudio 1.0:
|
|
* D3..2: Synch type (00 = None)
|
|
* D1..0: Transfer type (01 = Isochronous)
|
|
*/
|
|
uint16_t wMaxPacketSize;
|
|
uint8_t bInterval; /* MUST be set to 1 (full speed), +3 for high-speed? */
|
|
uint8_t bRefresh; /* USB Audio Class 1.0 specific: Range of 1 to 9 (full-speed). high-speed, probably range of 1 to 16? */
|
|
uint8_t bSynchAddress; /* USB Audio Class 1.0 specific: MUST be set to 0 */
|
|
} __attribute__ ((packed));
|
|
|
|
#define USB_AS_FORMAT_TYPE_I_UNDEFINED 0x0
|
|
#define USB_AS_FORMAT_TYPE_I_PCM 0x1
|
|
#define USB_AS_FORMAT_TYPE_I_PCM8 0x2
|
|
#define USB_AS_FORMAT_TYPE_I_IEEE_FLOAT 0x3
|
|
#define USB_AS_FORMAT_TYPE_I_ALAW 0x4
|
|
#define USB_AS_FORMAT_TYPE_I_MULAW 0x5
|
|
|
|
struct usb_as_format_type_i_discrete {
|
|
uint8_t bLength;
|
|
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
|
|
uint8_t bDescriptorSubType; /* USB_AS_FORMAT_TYPE */
|
|
uint8_t bFormatType; /* USB_AS_FORMAT_TYPE_I */
|
|
uint8_t bNrChannels;
|
|
uint8_t bSubframeSize;
|
|
uint8_t bBitResolution;
|
|
uint8_t bSamFreqType; /* Number of discrete frequencies */
|
|
uint8_t tSamFreq[][3];
|
|
} __attribute__ ((packed));
|
|
|
|
#define USB_AS_SIZEOF_FORMAT_TYPE_I_DISCRETE(n) (8 + (n * 3))
|
|
|
|
#endif /* USB_AUDIO_DEF_H */
|