// 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. #ifndef MEDIA_AUDIO_AUDIO_IO_H_ #define MEDIA_AUDIO_AUDIO_IO_H_ #include #include "base/time/time.h" #include "media/base/audio_bus.h" #include "media/base/media_export.h" // Low-level audio output support. To make sound there are 3 objects involved: // - AudioSource : produces audio samples on a pull model. Implements // the AudioSourceCallback interface. // - AudioOutputStream : uses the AudioSource to render audio on a given // channel, format and sample frequency configuration. Data from the // AudioSource is delivered in a 'pull' model. // - AudioManager : factory for the AudioOutputStream objects, manager // of the hardware resources and mixer control. // // The number and configuration of AudioOutputStream does not need to match the // physically available hardware resources. For example you can have: // // MonoPCMSource1 --> MonoPCMStream1 --> | | --> audio left channel // StereoPCMSource -> StereoPCMStream -> | mixer | // MonoPCMSource2 --> MonoPCMStream2 --> | | --> audio right channel // // This facility's objective is mix and render audio with low overhead using // the OS basic audio support, abstracting as much as possible the // idiosyncrasies of each platform. Non-goals: // - Positional, 3d audio // - Dependence on non-default libraries such as DirectX 9, 10, XAudio // - Digital signal processing or effects // - Extra features if a specific hardware is installed (EAX, X-fi) // // The primary client of this facility is audio coming from several tabs. // Specifically for this case we avoid supporting complex formats such as MP3 // or WMA. Complex format decoding should be done by the renderers. // Models an audio stream that gets rendered to the audio hardware output. // Because we support more audio streams than physically available channels // a given AudioOutputStream might or might not talk directly to hardware. // An audio stream allocates several buffers for audio data and calls // AudioSourceCallback::OnMoreData() periodically to fill these buffers, // as the data is written to the audio device. Size of each packet is determined // by |samples_per_packet| specified in AudioParameters when the stream is // created. namespace media { class MEDIA_EXPORT AudioOutputStream { public: // Audio sources must implement AudioSourceCallback. This interface will be // called in a random thread which very likely is a high priority thread. Do // not rely on using this thread TLS or make calls that alter the thread // itself such as creating Windows or initializing COM. class MEDIA_EXPORT AudioSourceCallback { public: virtual ~AudioSourceCallback() {} // Provide more data by fully filling |dest|. The source will return the // number of frames it filled. |delay| is the duration of audio written to // |dest| in prior calls to OnMoreData() that has not yet been played out, // and |delay_timestamp| is the time when |delay| was measured. The time // when the first sample added to |dest| is expected to be played out can be // calculated by adding |delay| to |delay_timestamp|. The accuracy of // |delay| and |delay_timestamp| may vary depending on the platform and // implementation. |prior_frames_skipped| is the number of frames skipped by // the consumer. virtual int OnMoreData(base::TimeDelta delay, base::TimeTicks delay_timestamp, int prior_frames_skipped, AudioBus* dest) = 0; // There was an error while playing a buffer. Audio source cannot be // destroyed yet. No direct action needed by the AudioStream, but it is // a good place to stop accumulating sound data since is is likely that // playback will not continue. // // An ErrorType may be provided with more information on what went wrong. An // unhandled kDeviceChange type error is likely to result in further errors; // so it's recommended that sources close their existing output stream and // request a new one when this error is sent. enum class ErrorType { kUnknown, kDeviceChange }; virtual void OnError(ErrorType type) = 0; }; virtual ~AudioOutputStream() {} // Open the stream. false is returned if the stream cannot be opened. Open() // must always be followed by a call to Close() even if Open() fails. virtual bool Open() = 0; // Starts playing audio and generating AudioSourceCallback::OnMoreData(). // Since implementor of AudioOutputStream may have internal buffers, right // after calling this method initial buffers are fetched. // // The output stream does not take ownership of this callback. virtual void Start(AudioSourceCallback* callback) = 0; // Stops playing audio. The operation completes synchronously meaning that // once Stop() has completed executing, no further callbacks will be made to // the callback object that was supplied to Start() and it can be safely // deleted. Stop() may be called in any state, e.g. before Start() or after // Stop(). virtual void Stop() = 0; // Sets the relative volume, with range [0.0, 1.0] inclusive. virtual void SetVolume(double volume) = 0; // Gets the relative volume, with range [0.0, 1.0] inclusive. virtual void GetVolume(double* volume) = 0; // Close the stream. // After calling this method, the object should not be used anymore. // After calling this method, no further AudioSourceCallback methods // should be called on the callback object that was supplied to Start() // by the AudioOutputStream implementation. virtual void Close() = 0; // Flushes the stream. This should only be called if the stream is not // playing. (i.e. called after Stop or Open) virtual void Flush() = 0; }; // Models an audio sink receiving recorded audio from the audio driver. class MEDIA_EXPORT AudioInputStream { public: class MEDIA_EXPORT AudioInputCallback { public: // Called by the audio recorder when a full packet of audio data is // available. This is called from a special audio thread and the // implementation should return as soon as possible. // // |capture_time| is the time at which the first sample in |source| was // received. The age of the audio data may be calculated by subtracting // |capture_time| from base::TimeTicks::Now(). |capture_time| is always // monotonically increasing. virtual void OnData(const AudioBus* source, base::TimeTicks capture_time, double volume) = 0; // There was an error while recording audio. The audio sink cannot be // destroyed yet. No direct action needed by the AudioInputStream, but it // is a good place to stop accumulating sound data since is is likely that // recording will not continue. virtual void OnError() = 0; protected: virtual ~AudioInputCallback() {} }; virtual ~AudioInputStream() {} // Open the stream and prepares it for recording. Call Start() to actually // begin recording. virtual bool Open() = 0; // Starts recording audio and generating AudioInputCallback::OnData(). // The input stream does not take ownership of this callback. virtual void Start(AudioInputCallback* callback) = 0; // Stops recording audio. Effect might not be instantaneous as there could be // pending audio callbacks in the queue which will be issued first before // recording stops. virtual void Stop() = 0; // Close the stream. This also generates AudioInputCallback::OnClose(). This // should be the last call made on this object. virtual void Close() = 0; // Returns the maximum microphone analog volume or 0.0 if device does not // have volume control. virtual double GetMaxVolume() = 0; // Sets the microphone analog volume, with range [0, max_volume] inclusive. virtual void SetVolume(double volume) = 0; // Returns the microphone analog volume, with range [0, max_volume] inclusive. virtual double GetVolume() = 0; // Sets the Automatic Gain Control (AGC) state. virtual bool SetAutomaticGainControl(bool enabled) = 0; // Returns the Automatic Gain Control (AGC) state. virtual bool GetAutomaticGainControl() = 0; // Returns the current muting state for the microphone. virtual bool IsMuted() = 0; // Sets the output device from which to cancel echo, if echo cancellation is // supported by this stream. E.g. called by WebRTC when it changes playback // devices. virtual void SetOutputDeviceForAec(const std::string& output_device_id) = 0; }; } // namespace media #endif // MEDIA_AUDIO_AUDIO_IO_H_