summaryrefslogtreecommitdiff
path: root/media/audio/win/core_audio_util_win.h
blob: 154a33a8a4bef19b6c1eaab6b9f1a0abef2c5916 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Utility methods for the Core Audio API on Windows.
// Always ensure that Core Audio is supported before using these methods.
// Use media::CoreAudioIsSupported() for this purpose.
// Also, all methods must be called on a valid COM thread. This can be done
// by using the base::win::ScopedCOMInitializer helper class.

#ifndef MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_
#define MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_

#include <audioclient.h>
#include <mmdeviceapi.h>
#include <string>

#include "base/basictypes.h"
#include "base/time/time.h"
#include "base/win/scoped_comptr.h"
#include "media/audio/audio_device_name.h"
#include "media/audio/audio_parameters.h"
#include "media/base/media_export.h"

using base::win::ScopedComPtr;

namespace media {

class MEDIA_EXPORT CoreAudioUtil {
 public:
  // Returns true if Windows Core Audio is supported.
  // Always verify that this method returns true before using any of the
  // methods in this class.
  static bool IsSupported();

  // Converts between reference time to base::TimeDelta.
  // One reference-time unit is 100 nanoseconds.
  // Example: double s = RefererenceTimeToTimeDelta(t).InMillisecondsF();
  static base::TimeDelta RefererenceTimeToTimeDelta(REFERENCE_TIME time);

  // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used
  // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default).
  static AUDCLNT_SHAREMODE GetShareMode();

  // The Windows Multimedia Device (MMDevice) API enables audio clients to
  // discover audio endpoint devices and determine their capabilities.

  // Number of active audio devices in the specified flow data flow direction.
  // Set |data_flow| to eAll to retrieve the total number of active audio
  // devices.
  static int NumberOfActiveDevices(EDataFlow data_flow);

  // Creates an IMMDeviceEnumerator interface which provides methods for
  // enumerating audio endpoint devices.
  static ScopedComPtr<IMMDeviceEnumerator> CreateDeviceEnumerator();

  // Creates a default endpoint device that is specified by a data-flow
  // direction and role, e.g. default render device.
  static ScopedComPtr<IMMDevice> CreateDefaultDevice(
      EDataFlow data_flow, ERole role);

  // Creates an endpoint device that is specified by a unique endpoint device-
  // identification string.
  static ScopedComPtr<IMMDevice> CreateDevice(const std::string& device_id);

  // Returns the unique ID and user-friendly name of a given endpoint device.
  // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}", and
  //          "Microphone (Realtek High Definition Audio)".
  static HRESULT GetDeviceName(IMMDevice* device, AudioDeviceName* name);

  // Returns the device ID/path of the controller (a.k.a. physical device that
  // |device| is connected to.  This ID will be the same for all devices from
  // the same controller so it is useful for doing things like determining
  // whether a set of output and input devices belong to the same controller.
  // The device enumerator is required as well as the device itself since
  // looking at the device topology is required and we need to open up
  // associated devices to determine the controller id.
  // If the ID could not be determined for some reason, an empty string is
  // returned.
  static std::string GetAudioControllerID(IMMDevice* device,
      IMMDeviceEnumerator* enumerator);

  // Gets the user-friendly name of the endpoint device which is represented
  // by a unique id in |device_id|.
  static std::string GetFriendlyName(const std::string& device_id);

  // Returns true if the provided unique |device_id| corresponds to the current
  // default device for the specified by a data-flow direction and role.
  static bool DeviceIsDefault(
      EDataFlow flow, ERole role, const std::string& device_id);

  // Query if the audio device is a rendering device or a capture device.
  static EDataFlow GetDataFlow(IMMDevice* device);

  // The Windows Audio Session API (WASAPI) enables client applications to
  // manage the flow of audio data between the application and an audio endpoint
  // device.

  // Create an IAudioClient interface for the default IMMDevice where
  // flow direction and role is define by |data_flow| and |role|.
  // The IAudioClient interface enables a client to create and initialize an
  // audio stream between an audio application and the audio engine (for a
  // shared-mode stream) or the hardware buffer of an audio endpoint device
  // (for an exclusive-mode stream).
  static ScopedComPtr<IAudioClient> CreateDefaultClient(EDataFlow data_flow,
                                                        ERole role);

  // Create an IAudioClient interface for an existing IMMDevice given by
  // |audio_device|. Flow direction and role is define by the |audio_device|.
  static ScopedComPtr<IAudioClient> CreateClient(IMMDevice* audio_device);

  // Get the mix format that the audio engine uses internally for processing
  // of shared-mode streams. This format is not necessarily a format that the
  // audio endpoint device supports. Thus, the caller might not succeed in
  // creating an exclusive-mode stream with a format obtained by this method.
  static HRESULT GetSharedModeMixFormat(IAudioClient* client,
                                        WAVEFORMATPCMEX* format);

  // Get the mix format that the audio engine uses internally for processing
  // of shared-mode streams using the default IMMDevice where flow direction
  // and role is define by |data_flow| and |role|.
  static HRESULT GetDefaultSharedModeMixFormat(EDataFlow data_flow,
                                               ERole role,
                                               WAVEFORMATPCMEX* format);

  // Returns true if the specified |client| supports the format in |format|
  // for the given |share_mode| (shared or exclusive).
  static bool IsFormatSupported(IAudioClient* client,
                                AUDCLNT_SHAREMODE share_mode,
                                const WAVEFORMATPCMEX* format);

  // Returns true if the specified |channel_layout| is supported for the
  // default IMMDevice where flow direction and role is define by |data_flow|
  // and |role|. If this method returns true for a certain channel layout, it
  // means that SharedModeInitialize() will succeed using a format based on
  // the preferred format where the channel layout has been modified.
  static bool IsChannelLayoutSupported(EDataFlow data_flow, ERole role,
                                       ChannelLayout channel_layout);

  // For a shared-mode stream, the audio engine periodically processes the
  // data in the endpoint buffer at the period obtained in |device_period|.
  // For an exclusive mode stream, |device_period| corresponds to the minimum
  // time interval between successive processing by the endpoint device.
  // This period plus the stream latency between the buffer and endpoint device
  // represents the minimum possible latency that an audio application can
  // achieve. The time in |device_period| is expressed in 100-nanosecond units.
  static HRESULT GetDevicePeriod(IAudioClient* client,
                                 AUDCLNT_SHAREMODE share_mode,
                                 REFERENCE_TIME* device_period);

  // Get the preferred audio parameters for the specified |client| or the
  // given direction and role is define by |data_flow| and |role|, or the
  // unique device id given by |device_id|.
  // The acquired values should only be utilized for shared mode streamed since
  // there are no preferred settings for an exclusive mode stream.
  static HRESULT GetPreferredAudioParameters(IAudioClient* client,
                                             AudioParameters* params);
  static HRESULT GetPreferredAudioParameters(EDataFlow data_flow, ERole role,
                                             AudioParameters* params);
  static HRESULT GetPreferredAudioParameters(const std::string& device_id,
                                             AudioParameters* params);

  // After activating an IAudioClient interface on an audio endpoint device,
  // the client must initialize it once, and only once, to initialize the audio
  // stream between the client and the device. In shared mode, the client
  // connects indirectly through the audio engine which does the mixing.
  // In exclusive mode, the client connects directly to the audio hardware.
  // If a valid event is provided in |event_handle|, the client will be
  // initialized for event-driven buffer handling. If |event_handle| is set to
  // NULL, event-driven buffer handling is not utilized.
  static HRESULT SharedModeInitialize(IAudioClient* client,
                                      const WAVEFORMATPCMEX* format,
                                      HANDLE event_handle,
                                      uint32* endpoint_buffer_size);
  // TODO(henrika): add ExclusiveModeInitialize(...)

  // Create an IAudioRenderClient client for an existing IAudioClient given by
  // |client|. The IAudioRenderClient interface enables a client to write
  // output data to a rendering endpoint buffer.
  static ScopedComPtr<IAudioRenderClient> CreateRenderClient(
      IAudioClient* client);

  // Create an IAudioCaptureClient client for an existing IAudioClient given by
  // |client|. The IAudioCaptureClient interface enables a client to read
  // input data from a capture endpoint buffer.
  static ScopedComPtr<IAudioCaptureClient> CreateCaptureClient(
      IAudioClient* client);

  // Fills up the endpoint rendering buffer with silence for an existing
  // IAudioClient given by |client| and a corresponding IAudioRenderClient
  // given by |render_client|.
  static bool FillRenderEndpointBufferWithSilence(
      IAudioClient* client, IAudioRenderClient* render_client);

 private:
  CoreAudioUtil() {}
  ~CoreAudioUtil() {}
  DISALLOW_COPY_AND_ASSIGN(CoreAudioUtil);
};

}  // namespace media

#endif  // MEDIA_AUDIO_WIN_CORE_AUDIO_UTIL_WIN_H_