Home | History | Annotate | Download | only in win
      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