1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Utility methods for the Core Audio API on Windows.
6 // Always ensure that Core Audio is supported before using these methods.
7 // Use media::CoreAudioIsSupported() for this purpose.
8 // Also, all methods must be called on a valid COM thread. This can be done
9 // by using the base::win::ScopedCOMInitializer helper class.
11 #ifndef MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_
12 #define MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_
14 #include <audioclient.h>
15 #include <mmdeviceapi.h>
18 #include "base/basictypes.h"
19 #include "base/time/time.h"
20 #include "base/win/scoped_comptr.h"
21 #include "media/audio/audio_device_name.h"
22 #include "media/audio/audio_parameters.h"
23 #include "media/base/media_export.h"
25 using base::win::ScopedComPtr
;
29 class MEDIA_EXPORT CoreAudioUtil
{
31 // Returns true if Windows Core Audio is supported.
32 // Always verify that this method returns true before using any of the
33 // methods in this class.
34 static bool IsSupported();
36 // Converts between reference time to base::TimeDelta.
37 // One reference-time unit is 100 nanoseconds.
38 // Example: double s = RefererenceTimeToTimeDelta(t).InMillisecondsF();
39 static base::TimeDelta
RefererenceTimeToTimeDelta(REFERENCE_TIME time
);
41 // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used
42 // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default).
43 static AUDCLNT_SHAREMODE
GetShareMode();
45 // The Windows Multimedia Device (MMDevice) API enables audio clients to
46 // discover audio endpoint devices and determine their capabilities.
48 // Number of active audio devices in the specified flow data flow direction.
49 // Set |data_flow| to eAll to retrieve the total number of active audio
51 static int NumberOfActiveDevices(EDataFlow data_flow
);
53 // Creates an IMMDeviceEnumerator interface which provides methods for
54 // enumerating audio endpoint devices.
55 static ScopedComPtr
<IMMDeviceEnumerator
> CreateDeviceEnumerator();
57 // Creates a default endpoint device that is specified by a data-flow
58 // direction and role, e.g. default render device.
59 static ScopedComPtr
<IMMDevice
> CreateDefaultDevice(
60 EDataFlow data_flow
, ERole role
);
62 // Creates an endpoint device that is specified by a unique endpoint device-
63 // identification string.
64 static ScopedComPtr
<IMMDevice
> CreateDevice(const std::string
& device_id
);
66 // Returns the unique ID and user-friendly name of a given endpoint device.
67 // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}", and
68 // "Microphone (Realtek High Definition Audio)".
69 static HRESULT
GetDeviceName(IMMDevice
* device
, AudioDeviceName
* name
);
71 // Returns the device ID/path of the controller (a.k.a. physical device that
72 // |device| is connected to. This ID will be the same for all devices from
73 // the same controller so it is useful for doing things like determining
74 // whether a set of output and input devices belong to the same controller.
75 // The device enumerator is required as well as the device itself since
76 // looking at the device topology is required and we need to open up
77 // associated devices to determine the controller id.
78 // If the ID could not be determined for some reason, an empty string is
80 static std::string
GetAudioControllerID(IMMDevice
* device
,
81 IMMDeviceEnumerator
* enumerator
);
83 // Accepts an id of an input device and finds a matching output device id.
84 // If the associated hardware does not have an audio output device (e.g.
85 // a webcam with a mic), an empty string is returned.
86 static std::string
GetMatchingOutputDeviceID(
87 const std::string
& input_device_id
);
89 // Gets the user-friendly name of the endpoint device which is represented
90 // by a unique id in |device_id|.
91 static std::string
GetFriendlyName(const std::string
& device_id
);
93 // Returns true if the provided unique |device_id| corresponds to the current
94 // default device for the specified by a data-flow direction and role.
95 static bool DeviceIsDefault(
96 EDataFlow flow
, ERole role
, const std::string
& device_id
);
98 // Query if the audio device is a rendering device or a capture device.
99 static EDataFlow
GetDataFlow(IMMDevice
* device
);
101 // The Windows Audio Session API (WASAPI) enables client applications to
102 // manage the flow of audio data between the application and an audio endpoint
105 // Create an IAudioClient interface for the default IMMDevice where
106 // flow direction and role is define by |data_flow| and |role|.
107 // The IAudioClient interface enables a client to create and initialize an
108 // audio stream between an audio application and the audio engine (for a
109 // shared-mode stream) or the hardware buffer of an audio endpoint device
110 // (for an exclusive-mode stream).
111 static ScopedComPtr
<IAudioClient
> CreateDefaultClient(EDataFlow data_flow
,
114 // Create an IAudioClient interface for an existing IMMDevice given by
115 // |audio_device|. Flow direction and role is define by the |audio_device|.
116 static ScopedComPtr
<IAudioClient
> CreateClient(IMMDevice
* audio_device
);
118 // Get the mix format that the audio engine uses internally for processing
119 // of shared-mode streams. This format is not necessarily a format that the
120 // audio endpoint device supports. Thus, the caller might not succeed in
121 // creating an exclusive-mode stream with a format obtained by this method.
122 static HRESULT
GetSharedModeMixFormat(IAudioClient
* client
,
123 WAVEFORMATPCMEX
* format
);
125 // Get the mix format that the audio engine uses internally for processing
126 // of shared-mode streams using the default IMMDevice where flow direction
127 // and role is define by |data_flow| and |role|.
128 static HRESULT
GetDefaultSharedModeMixFormat(EDataFlow data_flow
,
130 WAVEFORMATPCMEX
* format
);
132 // Returns true if the specified |client| supports the format in |format|
133 // for the given |share_mode| (shared or exclusive).
134 static bool IsFormatSupported(IAudioClient
* client
,
135 AUDCLNT_SHAREMODE share_mode
,
136 const WAVEFORMATPCMEX
* format
);
138 // Returns true if the specified |channel_layout| is supported for the
139 // default IMMDevice where flow direction and role is define by |data_flow|
140 // and |role|. If this method returns true for a certain channel layout, it
141 // means that SharedModeInitialize() will succeed using a format based on
142 // the preferred format where the channel layout has been modified.
143 static bool IsChannelLayoutSupported(EDataFlow data_flow
, ERole role
,
144 ChannelLayout channel_layout
);
146 // For a shared-mode stream, the audio engine periodically processes the
147 // data in the endpoint buffer at the period obtained in |device_period|.
148 // For an exclusive mode stream, |device_period| corresponds to the minimum
149 // time interval between successive processing by the endpoint device.
150 // This period plus the stream latency between the buffer and endpoint device
151 // represents the minimum possible latency that an audio application can
152 // achieve. The time in |device_period| is expressed in 100-nanosecond units.
153 static HRESULT
GetDevicePeriod(IAudioClient
* client
,
154 AUDCLNT_SHAREMODE share_mode
,
155 REFERENCE_TIME
* device_period
);
157 // Get the preferred audio parameters for the specified |client| or the
158 // given direction and role is define by |data_flow| and |role|, or the
159 // unique device id given by |device_id|.
160 // The acquired values should only be utilized for shared mode streamed since
161 // there are no preferred settings for an exclusive mode stream.
162 static HRESULT
GetPreferredAudioParameters(IAudioClient
* client
,
163 AudioParameters
* params
);
164 static HRESULT
GetPreferredAudioParameters(EDataFlow data_flow
, ERole role
,
165 AudioParameters
* params
);
166 static HRESULT
GetPreferredAudioParameters(const std::string
& device_id
,
167 AudioParameters
* params
);
169 // After activating an IAudioClient interface on an audio endpoint device,
170 // the client must initialize it once, and only once, to initialize the audio
171 // stream between the client and the device. In shared mode, the client
172 // connects indirectly through the audio engine which does the mixing.
173 // In exclusive mode, the client connects directly to the audio hardware.
174 // If a valid event is provided in |event_handle|, the client will be
175 // initialized for event-driven buffer handling. If |event_handle| is set to
176 // NULL, event-driven buffer handling is not utilized.
177 static HRESULT
SharedModeInitialize(IAudioClient
* client
,
178 const WAVEFORMATPCMEX
* format
,
180 uint32
* endpoint_buffer_size
);
181 // TODO(henrika): add ExclusiveModeInitialize(...)
183 // Create an IAudioRenderClient client for an existing IAudioClient given by
184 // |client|. The IAudioRenderClient interface enables a client to write
185 // output data to a rendering endpoint buffer.
186 static ScopedComPtr
<IAudioRenderClient
> CreateRenderClient(
187 IAudioClient
* client
);
189 // Create an IAudioCaptureClient client for an existing IAudioClient given by
190 // |client|. The IAudioCaptureClient interface enables a client to read
191 // input data from a capture endpoint buffer.
192 static ScopedComPtr
<IAudioCaptureClient
> CreateCaptureClient(
193 IAudioClient
* client
);
195 // Fills up the endpoint rendering buffer with silence for an existing
196 // IAudioClient given by |client| and a corresponding IAudioRenderClient
197 // given by |render_client|.
198 static bool FillRenderEndpointBufferWithSilence(
199 IAudioClient
* client
, IAudioRenderClient
* render_client
);
204 DISALLOW_COPY_AND_ASSIGN(CoreAudioUtil
);
209 #endif // MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_