Files
palemoon27/dom/media/webaudio/DelayNode.cpp
T
roytam1 c975675694 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1198459 - Update telemetry data based on the use of the forced enable pref. r=felipe (f33f0efc9a)
- Bug 1234210 - Restrict updates for accessibility.lastLoadDate to shutdown. r=trevor (5e484eb7ba)
- Bug 1231517 - part 3, Add ZoomToRect function to nsIWidget classes r=kats (57496a18cd)
- Bug 1229393 - Ensure that all the touch points from the original touch go to APZCCallbackHelper::SendSetTargetAPZCNotification. r=botond (45ce1737ac)
- Bug 1174323 part 1 - Add nsDOMWindowUtils::SendNativeMouseMove and EventUtils.sendNativeMouseMove. r=smaug (527439f71b)
- Bug 1180351 - Enable pointerlock tests on Windows and Linux. r=smaug (833fac9ba9)
- Bug 1180351 - Followup: Disable pointerlock tests on Windows for frequently failing tests. r=turning off tests (02525d24f4)
- Bug 1174323 part 2 - Use native mouse move to improve robustness of screenClientXYConst subtest. r=smaug (7e3fb884d3)
- Bug 1231517 - part 4, Add ZoomToFocusedInput function to nsDOMWindowUtils r=kats (a1f3e3b4fd)
- Bug 1153156 part.1 Move nsBaseWidget::OverrideSystemMouseScrollSpeed() to WidgetWheelEvent r=smaug, sr=smaug (8a95d65d55)
- bug 726265 don't activate ELAN swipe hack unless ScanCode is zero r=heycam (477a5ce06a)
- Bug 1235686 part.1 MouseScrollHandler should refresh the cache of system settings at handling wheel messages if the pref doesn't allow to cache system settings r=jimm (6cae8d2b07)
- Bug 1235686 part.2 Don't refresh the cache of system settings at handling wheel messages if the scroll amout values are initialized with prefs r=jimm (ead872b6bf)
- Bug 1235686 part.3 Don't trust system settings cache if SynTP of Synaptics is installed r=jimm (d56a034a42)
- Bug 1235686 part.4 Don't trust system settings cache if Apoint of Alps is installed r=jimm (85cb23e185)
- Bug 1153156 part.2 Make WidgetWheelEvent store if overriding system scroll speed is allowed and it shouldn't be allowed if scroll speed isn't system default settings on Windows r=smaug+jimm (3d5fc255db)
- Bug 1153156 part.3 Don't allow to override system scroll speed if the wheel event causes too fast scroll r=smaug+jimm (21e10640ac)
- Bug 1236750 - Rename ViewTransform to AsyncTransform. r=kats (1ccd8af262)
- Bug 1226826 - Record if painted displayport updates were due to repaints from the relevant layer tree or not. r=botond (e28315ec88)
- Bug 1228641. Add a initializer_list constructor to nsTArray. r=froydnj (448f69f610)
- Bug 962243 - Gtest for being able to pan after lifting a finger from a pinch. r=botond (a1687f190c)
- Bug 1031443 - Allow panning in the pinching state even if zooming is disabled;r=botond (aacb1a28bd)
- Bug 1231504 - Move some prefs from b2g.js to all.js. r=botond (c9801602ba)
- Bug 1092128 - Ensure the tests for touch action disabled actually disable touch action. r=botond (ec3fae4568)
- Bug 1014691 - Get TestAsyncPanZoomController to compile in its new location. r=kats (9dd104c6fd)
- Bug 1240244 - Split APZ gtests into several files. r=kats (0ce8bd4f80)
- Bug 1235994 - Add a flag to wheel events to track if they may have momentum following them. r=mstange (d5b2099244)
- Bug 1153156 part.4 Make APZC system scroll speed overriding aware r=mstange (f9d49eb79c)
- Bug 1233118 - implement IAccessible2_3::selectionRanges, r=yzen (d85fe6cf64)
- bug 1235965 - null check mDoc in AccessibleWrap::Shutdown() r=davidb (cb775e5c00)
- Bug 1130096 - Convert embedding/components/find/ to Gecko style. r=mccr8 (83d043e841)
- Bug 1164473 - Resolve issue when touches stop working after pen was activated. r=jimm (16ce68b032)
- Bug 1171712 - Implement separated InkColletor and InkCollectorEvent classes. r=smaug, r=jimm (8000e742b8)
- bug 1198656 interpret null ConvolverNode mBuffer as a buffer of zerosr=padenot (339e1f9904)
- bug 930257 finish Oscillator on processing last non-null block r=padenot (2719eee12b)
- Bug 1240411: P1. Clean up webaudio headers. r=cpearce (f169dc2789)
- Bug 1219711 - Don't rely on timer interval in fake audio track. r=jesup (f140fd848a)
- Bug 1223655 - Only check for track end if track exists in MediaEngineDefaultAudioSource. r=jesup (3055b4529f)
- Bug 1223655 - Also don't check time of data end if track has ended. r=jesup (bbdf7c5be5)
- Bug 1223655 - Fix opt build bustage on a CLOSED TREE. r=bustage (d546f4ba0b)
- Bug 1164463 followup: Add missing 'override' keyword to MediaEngineDefault::Shutdown(). rs=ehsan (33bf959d84)
- Bug 1240411: P2. Clean up webrtc headers. r=jesup (73c2bdf22d)
- Bug 1240411: P4. Clean up readers headers. r=cpearce (748d2bf9e8)
- Bug 1232527 - Remove GMPVideoDecoderTrialCreator and friends. r=jwwang (e0decf270f)
- Bug 1240411: P5. Clean up GMP headers. r=cpearce (0336b7fd9c)
- Bug 1240252: Add missing "mozilla::" namespace prefix before usage of type LayoutDeviceIntRegion, to fix local build bustage. r=njn (54d5a4a553)
- Bug 1245241 - part 1 - Close Shmem file handles after mapping them when possible to reduce exhaustion issues. r=billm (631c2b6da5)
2023-08-16 17:20:15 +08:00

234 lines
7.4 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include "DelayNode.h"
#include "mozilla/dom/DelayNodeBinding.h"
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include "AudioDestinationNode.h"
#include "WebAudioUtils.h"
#include "DelayBuffer.h"
#include "PlayingRefChangeHandler.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(DelayNode, AudioNode,
mDelay)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DelayNode)
NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(DelayNode, AudioNode)
NS_IMPL_RELEASE_INHERITED(DelayNode, AudioNode)
class DelayNodeEngine final : public AudioNodeEngine
{
typedef PlayingRefChangeHandler PlayingRefChanged;
public:
DelayNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination,
double aMaxDelayTicks)
: AudioNodeEngine(aNode)
, mDestination(aDestination->Stream())
// Keep the default value in sync with the default value in DelayNode::DelayNode.
, mDelay(0.f)
// Use a smoothing range of 20ms
, mBuffer(std::max(aMaxDelayTicks,
static_cast<double>(WEBAUDIO_BLOCK_SIZE)),
WebAudioUtils::ComputeSmoothingRate(0.02,
mDestination->SampleRate()))
, mMaxDelay(aMaxDelayTicks)
, mHaveProducedBeforeInput(false)
, mLeftOverData(INT32_MIN)
{
}
DelayNodeEngine* AsDelayNodeEngine() override
{
return this;
}
enum Parameters {
DELAY,
};
void RecvTimelineEvent(uint32_t aIndex,
AudioTimelineEvent& aEvent) override
{
MOZ_ASSERT(mDestination);
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
mDestination);
switch (aIndex) {
case DELAY:
mDelay.InsertEvent<int64_t>(aEvent);
break;
default:
NS_ERROR("Bad DelayNodeEngine TimelineParameter");
}
}
void ProcessBlock(AudioNodeStream* aStream,
GraphTime aFrom,
const AudioBlock& aInput,
AudioBlock* aOutput,
bool* aFinished) override
{
MOZ_ASSERT(aStream->SampleRate() == mDestination->SampleRate());
if (!aInput.IsSilentOrSubnormal()) {
if (mLeftOverData <= 0) {
RefPtr<PlayingRefChanged> refchanged =
new PlayingRefChanged(aStream, PlayingRefChanged::ADDREF);
aStream->Graph()->
DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
}
mLeftOverData = mBuffer.MaxDelayTicks();
} else if (mLeftOverData > 0) {
mLeftOverData -= WEBAUDIO_BLOCK_SIZE;
} else {
if (mLeftOverData != INT32_MIN) {
mLeftOverData = INT32_MIN;
aStream->ScheduleCheckForInactive();
// Delete our buffered data now we no longer need it
mBuffer.Reset();
RefPtr<PlayingRefChanged> refchanged =
new PlayingRefChanged(aStream, PlayingRefChanged::RELEASE);
aStream->Graph()->
DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
}
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
return;
}
mBuffer.Write(aInput);
// Skip output update if mLastChunks has already been set by
// ProduceBlockBeforeInput() when in a cycle.
if (!mHaveProducedBeforeInput) {
UpdateOutputBlock(aStream, aFrom, aOutput, 0.0);
}
mHaveProducedBeforeInput = false;
mBuffer.NextBlock();
}
void UpdateOutputBlock(AudioNodeStream* aStream, GraphTime aFrom,
AudioBlock* aOutput, double minDelay)
{
double maxDelay = mMaxDelay;
double sampleRate = aStream->SampleRate();
ChannelInterpretation channelInterpretation =
aStream->GetChannelInterpretation();
if (mDelay.HasSimpleValue()) {
// If this DelayNode is in a cycle, make sure the delay value is at least
// one block, even if that is greater than maxDelay.
double delayFrames = mDelay.GetValue() * sampleRate;
double delayFramesClamped =
std::max(minDelay, std::min(delayFrames, maxDelay));
mBuffer.Read(delayFramesClamped, aOutput, channelInterpretation);
} else {
// Compute the delay values for the duration of the input AudioChunk
// If this DelayNode is in a cycle, make sure the delay value is at least
// one block.
StreamTime tick = mDestination->GraphTimeToStreamTime(aFrom);
float values[WEBAUDIO_BLOCK_SIZE];
mDelay.GetValuesAtTime(tick, values,WEBAUDIO_BLOCK_SIZE);
double computedDelay[WEBAUDIO_BLOCK_SIZE];
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
double delayAtTick = values[counter] * sampleRate;
double delayAtTickClamped =
std::max(minDelay, std::min(delayAtTick, maxDelay));
computedDelay[counter] = delayAtTickClamped;
}
mBuffer.Read(computedDelay, aOutput, channelInterpretation);
}
}
void ProduceBlockBeforeInput(AudioNodeStream* aStream,
GraphTime aFrom,
AudioBlock* aOutput) override
{
if (mLeftOverData <= 0) {
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
} else {
UpdateOutputBlock(aStream, aFrom, aOutput, WEBAUDIO_BLOCK_SIZE);
}
mHaveProducedBeforeInput = true;
}
bool IsActive() const override
{
return mLeftOverData != INT32_MIN;
}
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
{
size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
// Not owned:
// - mDestination - probably not owned
// - mDelay - shares ref with AudioNode, don't count
amount += mBuffer.SizeOfExcludingThis(aMallocSizeOf);
return amount;
}
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override
{
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
AudioNodeStream* mDestination;
AudioParamTimeline mDelay;
DelayBuffer mBuffer;
double mMaxDelay;
bool mHaveProducedBeforeInput;
// How much data we have in our buffer which needs to be flushed out when our inputs
// finish.
int32_t mLeftOverData;
};
DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
: AudioNode(aContext,
2,
ChannelCountMode::Max,
ChannelInterpretation::Speakers)
, mDelay(new AudioParam(this, DelayNodeEngine::DELAY, 0.0f, "delayTime"))
{
DelayNodeEngine* engine =
new DelayNodeEngine(this, aContext->Destination(),
aContext->SampleRate() * aMaxDelay);
mStream = AudioNodeStream::Create(aContext, engine,
AudioNodeStream::NO_STREAM_FLAGS);
}
DelayNode::~DelayNode()
{
}
size_t
DelayNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
amount += mDelay->SizeOfIncludingThis(aMallocSizeOf);
return amount;
}
size_t
DelayNode::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
JSObject*
DelayNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return DelayNodeBinding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla