blob: 68ca60f352528f2863f8721d47a0572556ae6603 [file] [log] [blame]
/*
* Copyright (C) 2010, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_BUFFER_SOURCE_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_BUFFER_SOURCE_NODE_H_
#include <atomic>
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_param.h"
#include "third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.h"
#include "third_party/blink/renderer/modules/webaudio/panner_node.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
namespace blink {
class AudioBufferSourceOptions;
class BaseAudioContext;
// AudioBufferSourceNode is an AudioNode representing an audio source from an
// in-memory audio asset represented by an AudioBuffer. It generally will be
// used for short sounds which require a high degree of scheduling flexibility
// (can playback in rhythmically perfect ways).
class AudioBufferSourceHandler final : public AudioScheduledSourceHandler {
public:
static scoped_refptr<AudioBufferSourceHandler> Create(
AudioNode&,
float sample_rate,
AudioParamHandler& playback_rate,
AudioParamHandler& detune);
~AudioBufferSourceHandler() override;
// AudioHandler
void Process(uint32_t frames_to_process) override;
// setBuffer() is called on the main thread. This is the buffer we use for
// playback.
void SetBuffer(AudioBuffer*, ExceptionState&);
SharedAudioBuffer* Buffer() { return shared_buffer_.get(); }
// numberOfChannels() returns the number of output channels. This value
// equals the number of channels from the buffer. If a new buffer is set with
// a different number of channels, then this value will dynamically change.
unsigned NumberOfChannels();
// Play-state
void Start(double when, ExceptionState&);
void Start(double when, double grain_offset, ExceptionState&);
void Start(double when,
double grain_offset,
double grain_duration,
ExceptionState&);
// Note: the attribute was originally exposed as |.looping|, but to be more
// consistent in naming with <audio> and with how it's described in the
// specification, the proper attribute name is |.loop|. The old attribute is
// kept for backwards compatibility.
bool Loop() const { return is_looping_; }
void SetLoop(bool looping);
// Loop times in seconds.
double LoopStart() const { return loop_start_; }
double LoopEnd() const { return loop_end_; }
void SetLoopStart(double loop_start);
void SetLoopEnd(double loop_end);
// If we are no longer playing, propogate silence ahead to downstream nodes.
bool PropagatesSilence() const override;
void HandleStoppableSourceNode() override;
private:
AudioBufferSourceHandler(AudioNode&,
float sample_rate,
AudioParamHandler& playback_rate,
AudioParamHandler& detune);
void StartSource(double when,
double grain_offset,
double grain_duration,
bool is_duration_given,
ExceptionState&);
// Render audio directly from the buffer to the audio bus. Returns true on
// success, i.e., audio was written to the output bus because all the internal
// checks passed.
//
// output_bus -
// AudioBus where the rendered audio goes.
// destination_frame_offset -
// Index into the output bus where the first frame should be written.
// number_of_frames -
// Maximum number of frames to process; this can be less that a render
// quantum.
// start_time_offset -
// Actual start time relative to the |destination_frame_offset|. This
// should be the \sart_time_offset| value returned by
// |UpdateSchedulingInfo|.
bool RenderFromBuffer(AudioBus* output_bus,
unsigned destination_frame_offset,
uint32_t number_of_frames,
double start_time_offset);
// Render silence starting from "index" frame in AudioBus.
inline bool RenderSilenceAndFinishIfNotLooping(AudioBus*,
unsigned index,
uint32_t frames_to_process);
// Clamps grain parameters to the duration of the given AudioBuffer.
void ClampGrainParameters(const SharedAudioBuffer*);
// Sample data for the outputs of this node. The shared buffer can safely be
// accessed from the audio thread.
std::unique_ptr<SharedAudioBuffer> shared_buffer_;
// Pointers for the buffer and destination.
std::unique_ptr<const float* []> source_channels_;
std::unique_ptr<float* []> destination_channels_;
scoped_refptr<AudioParamHandler> playback_rate_;
scoped_refptr<AudioParamHandler> detune_;
bool DidSetLooping() const { return did_set_looping_; }
void SetDidSetLooping(bool loop) {
if (loop)
did_set_looping_ = true;
}
// If m_isLooping is false, then this node will be done playing and become
// inactive after it reaches the end of the sample data in the buffer. If
// true, it will wrap around to the start of the buffer each time it reaches
// the end.
//
// A process lock must be used to protect access.
bool is_looping_;
// True if the source .loop attribute was ever set.
// A process lock must be used to protect access.
bool did_set_looping_;
// A process lock must be used to protect access to both |loop_start_| and
// |loop_end_|.
double loop_start_;
double loop_end_;
// m_virtualReadIndex is a sample-frame index into our buffer representing the
// current playback position. Since it's floating-point, it has sub-sample
// accuracy.
double virtual_read_index_;
// Granular playback
bool is_grain_;
double grain_offset_; // in seconds
double grain_duration_; // in seconds
// True if grainDuration is given explicitly (via 3 arg start method).
bool is_duration_given_;
// Compute playback rate (k-rate) by incorporating the sample rate
// conversion factor, and the value of playbackRate and detune AudioParams.
double ComputePlaybackRate();
double GetMinPlaybackRate();
// The minimum playbackRate value ever used for this source.
double min_playback_rate_;
// True if the |buffer| attribute has ever been set to a non-null
// value. Defaults to false.
bool buffer_has_been_set_;
};
class AudioBufferSourceNode final : public AudioScheduledSourceNode {
DEFINE_WRAPPERTYPEINFO();
public:
static AudioBufferSourceNode* Create(BaseAudioContext&, ExceptionState&);
static AudioBufferSourceNode* Create(BaseAudioContext*,
AudioBufferSourceOptions*,
ExceptionState&);
AudioBufferSourceNode(BaseAudioContext&);
void Trace(Visitor*) const override;
AudioBufferSourceHandler& GetAudioBufferSourceHandler() const;
AudioBuffer* buffer() const;
void setBuffer(AudioBuffer*, ExceptionState&);
AudioParam* playbackRate() const;
AudioParam* detune() const;
bool loop() const;
void setLoop(bool);
double loopStart() const;
void setLoopStart(double);
double loopEnd() const;
void setLoopEnd(double);
void start(ExceptionState&);
void start(double when, ExceptionState&);
void start(double when, double grain_offset, ExceptionState&);
void start(double when,
double grain_offset,
double grain_duration,
ExceptionState&);
// InspectorHelperMixin
void ReportDidCreate() final;
void ReportWillBeDestroyed() final;
private:
Member<AudioParam> playback_rate_;
Member<AudioParam> detune_;
Member<AudioBuffer> buffer_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_BUFFER_SOURCE_NODE_H_