core_audio_util_win.h revision 116680a4aac90f2aa7413d9095a592090648e557
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.
4
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::CoreAudioUtil::IsSupported() 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.
10
11#ifndef MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_
12#define MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_
13
14#include <audioclient.h>
15#include <mmdeviceapi.h>
16#include <string>
17
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"
24
25using base::win::ScopedComPtr;
26
27namespace media {
28
29
30// Represents audio channel configuration constants as understood by Windows.
31// E.g. KSAUDIO_SPEAKER_MONO.  For a list of possible values see:
32// http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx
33typedef uint32 ChannelConfig;
34
35class MEDIA_EXPORT CoreAudioUtil {
36 public:
37  // Returns true if Windows Core Audio is supported.
38  // Always verify that this method returns true before using any of the
39  // methods in this class.
40  // WARNING: This function must be called once from the main thread before
41  // it is safe to call from other threads.
42  static bool IsSupported();
43
44  // Converts between reference time to base::TimeDelta.
45  // One reference-time unit is 100 nanoseconds.
46  // Example: double s = RefererenceTimeToTimeDelta(t).InMillisecondsF();
47  static base::TimeDelta RefererenceTimeToTimeDelta(REFERENCE_TIME time);
48
49  // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used
50  // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default).
51  static AUDCLNT_SHAREMODE GetShareMode();
52
53  // The Windows Multimedia Device (MMDevice) API enables audio clients to
54  // discover audio endpoint devices and determine their capabilities.
55
56  // Number of active audio devices in the specified flow data flow direction.
57  // Set |data_flow| to eAll to retrieve the total number of active audio
58  // devices.
59  static int NumberOfActiveDevices(EDataFlow data_flow);
60
61  // Creates an IMMDeviceEnumerator interface which provides methods for
62  // enumerating audio endpoint devices.
63  static ScopedComPtr<IMMDeviceEnumerator> CreateDeviceEnumerator();
64
65  // Creates a default endpoint device that is specified by a data-flow
66  // direction and role, e.g. default render device.
67  static ScopedComPtr<IMMDevice> CreateDefaultDevice(
68      EDataFlow data_flow, ERole role);
69
70  // Returns the device id of the default output device or an empty string
71  // if no such device exists or if the default device has been disabled.
72  static std::string GetDefaultOutputDeviceID();
73
74  // Creates an endpoint device that is specified by a unique endpoint device-
75  // identification string.
76  static ScopedComPtr<IMMDevice> CreateDevice(const std::string& device_id);
77
78  // Returns the unique ID and user-friendly name of a given endpoint device.
79  // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}", and
80  //          "Microphone (Realtek High Definition Audio)".
81  static HRESULT GetDeviceName(IMMDevice* device, AudioDeviceName* name);
82
83  // Returns the device ID/path of the controller (a.k.a. physical device that
84  // |device| is connected to.  This ID will be the same for all devices from
85  // the same controller so it is useful for doing things like determining
86  // whether a set of output and input devices belong to the same controller.
87  // The device enumerator is required as well as the device itself since
88  // looking at the device topology is required and we need to open up
89  // associated devices to determine the controller id.
90  // If the ID could not be determined for some reason, an empty string is
91  // returned.
92  static std::string GetAudioControllerID(IMMDevice* device,
93      IMMDeviceEnumerator* enumerator);
94
95  // Accepts an id of an input device and finds a matching output device id.
96  // If the associated hardware does not have an audio output device (e.g.
97  // a webcam with a mic), an empty string is returned.
98  static std::string GetMatchingOutputDeviceID(
99      const std::string& input_device_id);
100
101  // Gets the user-friendly name of the endpoint device which is represented
102  // by a unique id in |device_id|.
103  static std::string GetFriendlyName(const std::string& device_id);
104
105  // Returns true if the provided unique |device_id| corresponds to the current
106  // default device for the specified by a data-flow direction and role.
107  static bool DeviceIsDefault(
108      EDataFlow flow, ERole role, const std::string& device_id);
109
110  // Query if the audio device is a rendering device or a capture device.
111  static EDataFlow GetDataFlow(IMMDevice* device);
112
113  // The Windows Audio Session API (WASAPI) enables client applications to
114  // manage the flow of audio data between the application and an audio endpoint
115  // device.
116
117  // Create an IAudioClient instance for the default IMMDevice where
118  // flow direction and role is define by |data_flow| and |role|.
119  // The IAudioClient interface enables a client to create and initialize an
120  // audio stream between an audio application and the audio engine (for a
121  // shared-mode stream) or the hardware buffer of an audio endpoint device
122  // (for an exclusive-mode stream).
123  static ScopedComPtr<IAudioClient> CreateDefaultClient(EDataFlow data_flow,
124                                                        ERole role);
125
126  // Create an IAudioClient instance for a specific device _or_ the default
127  // device if |device_id| is empty.
128  static ScopedComPtr<IAudioClient> CreateClient(const std::string& device_id,
129                                                 EDataFlow data_flow,
130                                                 ERole role);
131
132  // Create an IAudioClient interface for an existing IMMDevice given by
133  // |audio_device|. Flow direction and role is define by the |audio_device|.
134  static ScopedComPtr<IAudioClient> CreateClient(IMMDevice* audio_device);
135
136  // Get the mix format that the audio engine uses internally for processing
137  // of shared-mode streams. This format is not necessarily a format that the
138  // audio endpoint device supports. Thus, the caller might not succeed in
139  // creating an exclusive-mode stream with a format obtained by this method.
140  static HRESULT GetSharedModeMixFormat(IAudioClient* client,
141                                        WAVEFORMATPCMEX* format);
142
143  // Returns true if the specified |client| supports the format in |format|
144  // for the given |share_mode| (shared or exclusive).
145  static bool IsFormatSupported(IAudioClient* client,
146                                AUDCLNT_SHAREMODE share_mode,
147                                const WAVEFORMATPCMEX* format);
148
149  // Returns true if the specified |channel_layout| is supported for the
150  // default IMMDevice where flow direction and role is define by |data_flow|
151  // and |role|. If this method returns true for a certain channel layout, it
152  // means that SharedModeInitialize() will succeed using a format based on
153  // the preferred format where the channel layout has been modified.
154  static bool IsChannelLayoutSupported(const std::string& device_id,
155                                       EDataFlow data_flow,
156                                       ERole role,
157                                       ChannelLayout channel_layout);
158
159  // For a shared-mode stream, the audio engine periodically processes the
160  // data in the endpoint buffer at the period obtained in |device_period|.
161  // For an exclusive mode stream, |device_period| corresponds to the minimum
162  // time interval between successive processing by the endpoint device.
163  // This period plus the stream latency between the buffer and endpoint device
164  // represents the minimum possible latency that an audio application can
165  // achieve. The time in |device_period| is expressed in 100-nanosecond units.
166  static HRESULT GetDevicePeriod(IAudioClient* client,
167                                 AUDCLNT_SHAREMODE share_mode,
168                                 REFERENCE_TIME* device_period);
169
170  // Get the preferred audio parameters for the specified |client| or the
171  // given direction and role is define by |data_flow| and |role|, or the
172  // unique device id given by |device_id|.
173  // The acquired values should only be utilized for shared mode streamed since
174  // there are no preferred settings for an exclusive mode stream.
175  static HRESULT GetPreferredAudioParameters(IAudioClient* client,
176                                             AudioParameters* params);
177  static HRESULT GetPreferredAudioParameters(EDataFlow data_flow, ERole role,
178                                             AudioParameters* params);
179  static HRESULT GetPreferredAudioParameters(const std::string& device_id,
180                                             AudioParameters* params);
181
182  // Retrieves an integer mask which corresponds to the channel layout the
183  // audio engine uses for its internal processing/mixing of shared-mode
184  // streams. This mask indicates which channels are present in the multi-
185  // channel stream. The least significant bit corresponds with the Front Left
186  // speaker, the next least significant bit corresponds to the Front Right
187  // speaker, and so on, continuing in the order defined in KsMedia.h.
188  // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx
189  // for more details.
190  // To get the channel config of the default device, pass an empty string
191  // for |device_id|.
192  static ChannelConfig GetChannelConfig(const std::string& device_id,
193                                        EDataFlow data_flow);
194
195  // After activating an IAudioClient interface on an audio endpoint device,
196  // the client must initialize it once, and only once, to initialize the audio
197  // stream between the client and the device. In shared mode, the client
198  // connects indirectly through the audio engine which does the mixing.
199  // In exclusive mode, the client connects directly to the audio hardware.
200  // If a valid event is provided in |event_handle|, the client will be
201  // initialized for event-driven buffer handling. If |event_handle| is set to
202  // NULL, event-driven buffer handling is not utilized.
203  // This function will initialize the audio client as part of the default
204  // audio session if NULL is passed for |session_guid|, otherwise the client
205  // will be associated with the specified session.
206  static HRESULT SharedModeInitialize(IAudioClient* client,
207                                      const WAVEFORMATPCMEX* format,
208                                      HANDLE event_handle,
209                                      uint32* endpoint_buffer_size,
210                                      const GUID* session_guid);
211
212  // TODO(henrika): add ExclusiveModeInitialize(...)
213
214  // Create an IAudioRenderClient client for an existing IAudioClient given by
215  // |client|. The IAudioRenderClient interface enables a client to write
216  // output data to a rendering endpoint buffer.
217  static ScopedComPtr<IAudioRenderClient> CreateRenderClient(
218      IAudioClient* client);
219
220  // Create an IAudioCaptureClient client for an existing IAudioClient given by
221  // |client|. The IAudioCaptureClient interface enables a client to read
222  // input data from a capture endpoint buffer.
223  static ScopedComPtr<IAudioCaptureClient> CreateCaptureClient(
224      IAudioClient* client);
225
226  // Fills up the endpoint rendering buffer with silence for an existing
227  // IAudioClient given by |client| and a corresponding IAudioRenderClient
228  // given by |render_client|.
229  static bool FillRenderEndpointBufferWithSilence(
230      IAudioClient* client, IAudioRenderClient* render_client);
231
232 private:
233  CoreAudioUtil() {}
234  ~CoreAudioUtil() {}
235  DISALLOW_COPY_AND_ASSIGN(CoreAudioUtil);
236};
237
238// The special audio session identifier we use when opening up the default
239// communication device.  This has the effect that a separate volume control
240// will be shown in the system's volume mixer and control over ducking and
241// visually observing the behavior of ducking, is easier.
242// Use with |SharedModeInitialize|.
243extern const GUID kCommunicationsSessionId;
244
245}  // namespace media
246
247#endif  // MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_
248