waveout_output_win.h revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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#ifndef MEDIA_AUDIO_WIN_WAVEOUT_OUTPUT_WIN_H_
6#define MEDIA_AUDIO_WIN_WAVEOUT_OUTPUT_WIN_H_
7
8#include <windows.h>
9#include <mmsystem.h>
10#include <mmreg.h>
11
12#include "base/basictypes.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/synchronization/lock.h"
15#include "base/win/scoped_handle.h"
16#include "media/audio/audio_io.h"
17#include "media/audio/audio_parameters.h"
18
19namespace media {
20
21class AudioManagerWin;
22
23// Implements PCM audio output support for Windows using the WaveXXX API.
24// While not as nice as the DirectSound-based API, it should work in all target
25// operating systems regardless or DirectX version installed. It is known that
26// in some machines WaveXXX based audio is better while in others DirectSound
27// is better.
28//
29// Important: the OnXXXX functions in AudioSourceCallback are called by more
30// than one thread so it is important to have some form of synchronization if
31// you are keeping state in it.
32class PCMWaveOutAudioOutputStream : public AudioOutputStream {
33 public:
34  // The ctor takes all the usual parameters, plus |manager| which is the the
35  // audio manager who is creating this object and |device_id| which is provided
36  // by the operating system.
37  PCMWaveOutAudioOutputStream(AudioManagerWin* manager,
38                              const AudioParameters& params,
39                              int num_buffers,
40                              UINT device_id);
41  virtual ~PCMWaveOutAudioOutputStream();
42
43  // Implementation of AudioOutputStream.
44  virtual bool Open();
45  virtual void Close();
46  virtual void Start(AudioSourceCallback* callback);
47  virtual void Stop();
48  virtual void SetVolume(double volume);
49  virtual void GetVolume(double* volume);
50
51  // Sends a buffer to the audio driver for playback.
52  void QueueNextPacket(WAVEHDR* buffer);
53
54 private:
55  enum State {
56    PCMA_BRAND_NEW,    // Initial state.
57    PCMA_READY,        // Device obtained and ready to play.
58    PCMA_PLAYING,      // Playing audio.
59    PCMA_STOPPING,     // Audio is stopping, do not "feed" data to Windows.
60    PCMA_CLOSED        // Device has been released.
61  };
62
63  // Returns pointer to the n-th buffer.
64  inline WAVEHDR* GetBuffer(int n) const;
65
66  // Size of one buffer in bytes, rounded up if necessary.
67  inline size_t BufferSize() const;
68
69  // Windows calls us back asking for more data when buffer_event_ signalled.
70  // See MSDN for help on RegisterWaitForSingleObject() and waveOutOpen().
71  static void NTAPI BufferCallback(PVOID lpParameter, BOOLEAN timer_fired);
72
73  // If windows reports an error this function handles it and passes it to
74  // the attached AudioSourceCallback::OnError().
75  void HandleError(MMRESULT error);
76
77  // Allocates and prepares the memory that will be used for playback.
78  void SetupBuffers();
79
80  // Deallocates the memory allocated in SetupBuffers.
81  void FreeBuffers();
82
83  // Reader beware. Visual C has stronger guarantees on volatile vars than
84  // most people expect. In fact, it has release semantics on write and
85  // acquire semantics on reads. See the msdn documentation.
86  volatile State state_;
87
88  // The audio manager that created this output stream. We notify it when
89  // we close so it can release its own resources.
90  AudioManagerWin* manager_;
91
92  // We use the callback mostly to periodically request more audio data.
93  AudioSourceCallback* callback_;
94
95  // The number of buffers of size |buffer_size_| each to use.
96  const int num_buffers_;
97
98  // The size in bytes of each audio buffer, we usually have two of these.
99  uint32 buffer_size_;
100
101  // Volume level from 0 to 1.
102  float volume_;
103
104  // Channels from 0 to 8.
105  const int channels_;
106
107  // Number of bytes yet to be played in the hardware buffer.
108  uint32 pending_bytes_;
109
110  // The id assigned by the operating system to the selected wave output
111  // hardware device. Usually this is just -1 which means 'default device'.
112  UINT device_id_;
113
114  // Windows native structure to encode the format parameters.
115  WAVEFORMATPCMEX format_;
116
117  // Handle to the instance of the wave device.
118  HWAVEOUT waveout_;
119
120  // Handle to the buffer event.
121  base::win::ScopedHandle buffer_event_;
122
123  // Handle returned by RegisterWaitForSingleObject().
124  HANDLE waiting_handle_;
125
126  // Pointer to the allocated audio buffers, we allocate all buffers in one big
127  // chunk. This object owns them.
128  scoped_ptr<char[]> buffers_;
129
130  // Lock used to avoid the conflict when callbacks are called simultaneously.
131  base::Lock lock_;
132
133  // Container for retrieving data from AudioSourceCallback::OnMoreData().
134  scoped_ptr<AudioBus> audio_bus_;
135
136  DISALLOW_COPY_AND_ASSIGN(PCMWaveOutAudioOutputStream);
137};
138
139}  // namespace media
140
141#endif  // MEDIA_AUDIO_WIN_WAVEOUT_OUTPUT_WIN_H_
142