root/media/base/audio_splicer.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// 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_BASE_AUDIO_SPLICER_H_
#define MEDIA_BASE_AUDIO_SPLICER_H_

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "media/audio/audio_parameters.h"
#include "media/base/buffers.h"
#include "media/base/media_export.h"

namespace media {

class AudioBuffer;
class AudioBus;
class AudioStreamSanitizer;

// Helper class that handles filling gaps and resolving overlaps.
class MEDIA_EXPORT AudioSplicer {
 public:
  explicit AudioSplicer(int samples_per_second);
  ~AudioSplicer();

  enum {
    // The number of ms to crossfade before trimming when buffers overlap.
    kCrossfadeDurationInMilliseconds = 5,
  };

  // Resets the splicer state by clearing the output buffers queue and resetting
  // the timestamp helper.
  void Reset();

  // Adds a new buffer full of samples or end of stream buffer to the splicer.
  // Returns true if the buffer was accepted.  False is returned if an error
  // occurred.
  bool AddInput(const scoped_refptr<AudioBuffer>& input);

  // Returns true if the splicer has a buffer to return.
  bool HasNextBuffer() const;

  // Removes the next buffer from the output buffer queue and returns it; this
  // should only be called if HasNextBuffer() returns true.
  scoped_refptr<AudioBuffer> GetNextBuffer();

  // Indicates that overlapping buffers are coming up and should be crossfaded.
  // Once set, all buffers encountered after |splice_timestamp| will be queued
  // internally until at least 5ms of overlapping buffers are received (or end
  // of stream, whichever comes first).
  void SetSpliceTimestamp(base::TimeDelta splice_timestamp);

 private:
  friend class AudioSplicerTest;

  // Extracts frames to be crossfaded from |pre_splice_sanitizer_|.  Transfers
  // all frames before |splice_timestamp_| into |output_sanitizer_| and drops
  // frames outside of the crossfade duration.
  //
  // The size of the returned AudioBus is the crossfade duration in frames.
  // Crossfade duration is calculated based on the number of frames available
  // after |splice_timestamp_| in each sanitizer and capped by
  // |max_crossfade_duration_|.
  //
  // |pre_splice_sanitizer_| will be empty after this operation.
  scoped_ptr<AudioBus> ExtractCrossfadeFromPreSplice(
      scoped_refptr<AudioBuffer>* crossfade_buffer);

  // Crossfades |pre_splice_bus->frames()| frames from
  // |post_splice_sanitizer_|
  // with those from |pre_splice_bus|.  Adds the crossfaded buffer to
  // |output_sanitizer_| along with all buffers in |post_splice_sanitizer_|.
  //
  // |post_splice_sanitizer_| will be empty after this operation.
  void CrossfadePostSplice(scoped_ptr<AudioBus> pre_splice_bus,
                           scoped_refptr<AudioBuffer> crossfade_buffer);

  // Reset the splice and splice end timestamps.
  void reset_splice_timestamps() {
    splice_timestamp_ = max_splice_end_timestamp_ = kNoTimestamp();
  }

  const base::TimeDelta max_crossfade_duration_;
  base::TimeDelta splice_timestamp_;
  base::TimeDelta max_splice_end_timestamp_;

  // The various sanitizers for each stage of the crossfade process.  Buffers in
  // |output_sanitizer_| are immediately available for consumption by external
  // callers.
  //
  // Overlapped buffers go into the |pre_splice_sanitizer_| while overlapping
  // buffers go into the |post_splice_sanitizer_|.  Once enough buffers for
  // crossfading are received the pre and post sanitizers are drained into
  // |output_sanitizer_| by the two ExtractCrossfadeFromXXX methods above.
  //
  // |pre_splice_sanitizer_| is not constructed until the first splice frame is
  // encountered.  At which point it is constructed based on the timestamp state
  // of |output_sanitizer_|.  It is destructed once the splice is finished.
  scoped_ptr<AudioStreamSanitizer> output_sanitizer_;
  scoped_ptr<AudioStreamSanitizer> pre_splice_sanitizer_;
  scoped_ptr<AudioStreamSanitizer> post_splice_sanitizer_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSplicer);
};

}  // namespace media

#endif

/* [<][>][^][v][top][bottom][index][help] */