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 19 namespace media { 20 21 class 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. 32 class 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