2008-07-29 23:50:14 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2012-11-14 11:46:40 -08:00
|
|
|
#if !defined(AudioStream_h_)
|
|
|
|
#define AudioStream_h_
|
2008-11-06 12:53:20 -08:00
|
|
|
|
2008-07-29 23:50:14 -07:00
|
|
|
#include "nscore.h"
|
2012-10-25 03:09:40 -07:00
|
|
|
#include "AudioSampleFormat.h"
|
2012-11-15 19:25:26 -08:00
|
|
|
#include "AudioChannelCommon.h"
|
2012-11-22 02:38:28 -08:00
|
|
|
#include "soundtouch/SoundTouch.h"
|
2012-11-28 08:25:57 -08:00
|
|
|
#include "nsAutoPtr.h"
|
2008-07-29 23:50:14 -07:00
|
|
|
|
2012-11-14 11:45:33 -08:00
|
|
|
namespace mozilla {
|
|
|
|
|
2012-11-22 02:38:28 -08:00
|
|
|
class AudioStream;
|
|
|
|
|
|
|
|
class AudioClock
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AudioClock(mozilla::AudioStream* aStream);
|
|
|
|
// Initialize the clock with the current AudioStream. Need to be called
|
|
|
|
// before querying the clock. Called on the audio thread.
|
|
|
|
void Init();
|
|
|
|
// Update the number of samples that has been written in the audio backend.
|
|
|
|
// Called on the state machine thread.
|
|
|
|
void UpdateWritePosition(uint32_t aCount);
|
|
|
|
// Get the read position of the stream, in microseconds.
|
|
|
|
// Called on the state machine thead.
|
|
|
|
uint64_t GetPosition();
|
|
|
|
// Get the read position of the stream, in frames.
|
|
|
|
// Called on the state machine thead.
|
|
|
|
uint64_t GetPositionInFrames();
|
|
|
|
// Set the playback rate.
|
|
|
|
// Called on the audio thread.
|
|
|
|
void SetPlaybackRate(double aPlaybackRate);
|
|
|
|
// Get the current playback rate.
|
|
|
|
// Called on the audio thread.
|
|
|
|
double GetPlaybackRate();
|
|
|
|
// Set if we are preserving the pitch.
|
|
|
|
// Called on the audio thread.
|
|
|
|
void SetPreservesPitch(bool aPreservesPitch);
|
|
|
|
// Get the current pitch preservation state.
|
|
|
|
// Called on the audio thread.
|
|
|
|
bool GetPreservesPitch();
|
2012-11-26 06:13:08 -08:00
|
|
|
// Get the number of frames written to the backend.
|
|
|
|
int64_t GetWritten();
|
2012-11-22 02:38:28 -08:00
|
|
|
private:
|
|
|
|
// This AudioStream holds a strong reference to this AudioClock. This
|
|
|
|
// pointer is garanteed to always be valid.
|
|
|
|
AudioStream* mAudioStream;
|
|
|
|
// The old output rate, to compensate audio latency for the period inbetween
|
|
|
|
// the moment resampled buffers are pushed to the hardware and the moment the
|
|
|
|
// clock should take the new rate into account for A/V sync.
|
|
|
|
int mOldOutRate;
|
|
|
|
// Position at which the last playback rate change occured
|
|
|
|
int64_t mBasePosition;
|
|
|
|
// Offset, in frames, at which the last playback rate change occured
|
|
|
|
int64_t mBaseOffset;
|
|
|
|
// Old base offset (number of samples), used when changing rate to compute the
|
|
|
|
// position in the stream.
|
|
|
|
int64_t mOldBaseOffset;
|
|
|
|
// Old base position (number of microseconds), when changing rate. This is the
|
|
|
|
// time in the media, not wall clock position.
|
|
|
|
int64_t mOldBasePosition;
|
|
|
|
// Write position at which the playbackRate change occured.
|
|
|
|
int64_t mPlaybackRateChangeOffset;
|
|
|
|
// The previous position reached in the media, used when compensating
|
|
|
|
// latency, to have the position at which the playbackRate change occured.
|
|
|
|
int64_t mPreviousPosition;
|
|
|
|
// Number of samples effectivelly written in backend, i.e. write position.
|
|
|
|
int64_t mWritten;
|
|
|
|
// Output rate in Hz (characteristic of the playback rate)
|
|
|
|
int mOutRate;
|
|
|
|
// Input rate in Hz (characteristic of the media being played)
|
|
|
|
int mInRate;
|
|
|
|
// True if the we are timestretching, false if we are resampling.
|
|
|
|
bool mPreservesPitch;
|
Backout b3a8618f901c (bug 829042), 34a9ef8f929d (bug 822933), 4c1215cefbab (bug 826349), 70bb7f775178 (bug 825325), e9c8447fb197 (bug 828713), eb6ebf01eafe (bug 828901), f1f3ef647920 (bug 825329), f9d7b5722d4f (bug 825329), 5add564d4546 (bug 819377), 55e93d1fa972 (bug 804875), f14639a3461e (bug 804875), 23456fc21052 (bug 814308) for Windows pgo-only mochitest-1 media test timeouts on a CLOSED TREE
2013-01-16 07:16:23 -08:00
|
|
|
// The current playback rate.
|
|
|
|
double mPlaybackRate;
|
2012-11-22 02:38:28 -08:00
|
|
|
// True if we are playing at the old playbackRate after it has been changed.
|
|
|
|
bool mCompensatingLatency;
|
|
|
|
};
|
|
|
|
|
2012-05-31 21:45:01 -07:00
|
|
|
// Access to a single instance of this class must be synchronized by
|
|
|
|
// callers, or made from a single thread. One exception is that access to
|
2012-10-25 03:09:39 -07:00
|
|
|
// GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels}
|
2012-05-31 21:45:01 -07:00
|
|
|
// is thread-safe without external synchronization.
|
2012-11-21 19:38:39 -08:00
|
|
|
class AudioStream
|
2008-07-29 23:50:14 -07:00
|
|
|
{
|
2010-11-16 20:14:19 -08:00
|
|
|
public:
|
2012-11-22 02:38:28 -08:00
|
|
|
AudioStream();
|
2012-02-13 20:39:33 -08:00
|
|
|
|
2012-11-14 11:46:40 -08:00
|
|
|
virtual ~AudioStream();
|
2011-01-03 19:55:32 -08:00
|
|
|
|
2008-11-10 00:12:13 -08:00
|
|
|
// Initialize Audio Library. Some Audio backends require initializing the
|
2011-09-26 20:31:18 -07:00
|
|
|
// library before using it.
|
2008-10-28 09:17:59 -07:00
|
|
|
static void InitLibrary();
|
2008-07-29 23:50:14 -07:00
|
|
|
|
2008-11-10 00:12:13 -08:00
|
|
|
// Shutdown Audio Library. Some Audio backends require shutting down the
|
|
|
|
// library after using it.
|
2008-07-29 23:50:14 -07:00
|
|
|
static void ShutdownLibrary();
|
|
|
|
|
2010-11-16 20:14:19 -08:00
|
|
|
// AllocateStream will return either a local stream or a remoted stream
|
2011-04-02 19:14:00 -07:00
|
|
|
// depending on where you call it from. If you call this from a child process,
|
|
|
|
// you may receive an implementation which forwards to a compositing process.
|
2012-11-14 11:46:40 -08:00
|
|
|
static AudioStream* AllocateStream();
|
2008-07-29 23:50:14 -07:00
|
|
|
|
2011-09-26 20:31:18 -07:00
|
|
|
// Initialize the audio stream. aNumChannels is the number of audio
|
|
|
|
// channels (1 for mono, 2 for stereo, etc) and aRate is the sample rate
|
|
|
|
// (22050Hz, 44100Hz, etc).
|
2012-11-15 19:25:26 -08:00
|
|
|
virtual nsresult Init(int32_t aNumChannels, int32_t aRate,
|
2012-11-18 16:54:29 -08:00
|
|
|
const dom::AudioChannelType aAudioStreamType) = 0;
|
2008-07-29 23:50:14 -07:00
|
|
|
|
|
|
|
// Closes the stream. All future use of the stream is an error.
|
2010-11-16 20:14:19 -08:00
|
|
|
virtual void Shutdown() = 0;
|
2008-07-29 23:50:14 -07:00
|
|
|
|
2012-10-25 03:10:51 -07:00
|
|
|
// Write audio data to the audio hardware. aBuf is an array of AudioDataValues
|
|
|
|
// AudioDataValue of length aFrames*mChannels. If aFrames is larger
|
2011-09-26 20:31:18 -07:00
|
|
|
// than the result of Available(), the write will block until sufficient
|
|
|
|
// buffer space is available.
|
2012-10-25 03:10:51 -07:00
|
|
|
virtual nsresult Write(const mozilla::AudioDataValue* aBuf, uint32_t aFrames) = 0;
|
2008-07-29 23:50:14 -07:00
|
|
|
|
2011-09-26 20:31:18 -07:00
|
|
|
// Return the number of audio frames that can be written without blocking.
|
2012-08-22 08:56:38 -07:00
|
|
|
virtual uint32_t Available() = 0;
|
2008-10-19 00:39:21 -07:00
|
|
|
|
2008-07-29 23:50:14 -07:00
|
|
|
// Set the current volume of the audio playback. This is a value from
|
2012-05-31 21:45:01 -07:00
|
|
|
// 0 (meaning muted) to 1 (meaning full volume). Thread-safe.
|
2011-01-16 19:03:00 -08:00
|
|
|
virtual void SetVolume(double aVolume) = 0;
|
2008-07-29 23:50:14 -07:00
|
|
|
|
2008-11-06 12:53:20 -08:00
|
|
|
// Block until buffered audio data has been consumed.
|
2010-11-16 20:14:19 -08:00
|
|
|
virtual void Drain() = 0;
|
2008-11-06 12:53:20 -08:00
|
|
|
|
2012-11-26 06:13:08 -08:00
|
|
|
// Start the stream.
|
|
|
|
virtual nsresult Start() = 0;
|
|
|
|
|
|
|
|
// Check if the stream is started.
|
|
|
|
virtual bool IsStarted() = 0;
|
|
|
|
|
|
|
|
// Return the number of frames written so far in the stream. This allow the
|
|
|
|
// caller to check if it is safe to start the stream, if needed.
|
|
|
|
virtual int64_t GetWritten();
|
|
|
|
|
|
|
|
// Pause audio playback.
|
2010-11-16 20:14:19 -08:00
|
|
|
virtual void Pause() = 0;
|
2009-05-14 18:29:05 -07:00
|
|
|
|
2012-11-26 06:13:08 -08:00
|
|
|
// Resume audio playback.
|
2010-11-16 20:14:19 -08:00
|
|
|
virtual void Resume() = 0;
|
2009-05-14 18:29:05 -07:00
|
|
|
|
2011-09-26 20:31:18 -07:00
|
|
|
// Return the position in microseconds of the audio frame being played by
|
2012-11-22 02:38:28 -08:00
|
|
|
// the audio hardware, compensated for playback rate change. Thread-safe.
|
2012-08-22 08:56:38 -07:00
|
|
|
virtual int64_t GetPosition() = 0;
|
2010-04-01 20:03:07 -07:00
|
|
|
|
2011-09-26 20:31:18 -07:00
|
|
|
// Return the position, measured in audio frames played since the stream
|
2012-05-31 21:45:01 -07:00
|
|
|
// was opened, of the audio hardware. Thread-safe.
|
2012-08-22 08:56:38 -07:00
|
|
|
virtual int64_t GetPositionInFrames() = 0;
|
2010-08-25 06:10:00 -07:00
|
|
|
|
2012-11-22 02:38:28 -08:00
|
|
|
// Return the position, measured in audio framed played since the stream was
|
|
|
|
// opened, of the audio hardware, not adjusted for the changes of playback
|
|
|
|
// rate.
|
|
|
|
virtual int64_t GetPositionInFramesInternal() = 0;
|
|
|
|
|
2011-09-29 16:34:37 -07:00
|
|
|
// Returns true when the audio stream is paused.
|
2011-09-28 23:19:26 -07:00
|
|
|
virtual bool IsPaused() = 0;
|
2010-11-29 21:37:32 -08:00
|
|
|
|
2011-09-26 20:31:18 -07:00
|
|
|
// Returns the minimum number of audio frames which must be written before
|
2010-12-19 11:05:40 -08:00
|
|
|
// you can be sure that something will be played.
|
2012-08-22 08:56:38 -07:00
|
|
|
virtual int32_t GetMinWriteSize() = 0;
|
2010-12-19 11:05:40 -08:00
|
|
|
|
2012-11-22 02:38:28 -08:00
|
|
|
int GetRate() { return mOutRate; }
|
2012-02-13 20:39:33 -08:00
|
|
|
int GetChannels() { return mChannels; }
|
2012-10-25 03:09:38 -07:00
|
|
|
|
2012-11-29 06:40:57 -08:00
|
|
|
// This should be called before attempting to use the time stretcher.
|
2013-01-18 05:21:47 -08:00
|
|
|
virtual void EnsureTimeStretcherInitialized();
|
2012-11-22 02:38:28 -08:00
|
|
|
// Set playback rate as a multiple of the intrinsic playback rate. This is to
|
|
|
|
// be called only with aPlaybackRate > 0.0.
|
|
|
|
virtual nsresult SetPlaybackRate(double aPlaybackRate);
|
|
|
|
// Switch between resampling (if false) and time stretching (if true, default).
|
|
|
|
virtual nsresult SetPreservesPitch(bool aPreservesPitch);
|
|
|
|
|
2010-11-29 21:37:32 -08:00
|
|
|
protected:
|
2012-11-22 02:38:28 -08:00
|
|
|
// Input rate in Hz (characteristic of the media being played)
|
|
|
|
int mInRate;
|
|
|
|
// Output rate in Hz (characteristic of the playback rate)
|
|
|
|
int mOutRate;
|
2012-02-13 20:39:33 -08:00
|
|
|
int mChannels;
|
2012-11-26 06:13:08 -08:00
|
|
|
// Number of frames written to the buffers.
|
|
|
|
int64_t mWritten;
|
2012-11-22 02:38:28 -08:00
|
|
|
AudioClock mAudioClock;
|
2012-11-28 08:25:57 -08:00
|
|
|
nsAutoPtr<soundtouch::SoundTouch> mTimeStretcher;
|
2008-07-29 23:50:14 -07:00
|
|
|
};
|
2010-11-16 20:14:19 -08:00
|
|
|
|
2012-11-14 11:45:33 -08:00
|
|
|
} // namespace mozilla
|
|
|
|
|
2008-11-06 12:53:20 -08:00
|
|
|
#endif
|