summaryrefslogtreecommitdiffstats
path: root/dom/media/webaudio/AudioParamTimeline.h
blob: bd0ba99ffe5898a39f1446b2e4d0490421e18150 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* -*- 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/. */

#ifndef AudioParamTimeline_h_
#define AudioParamTimeline_h_

#include "AudioEventTimeline.h"
#include "AudioNodeTrack.h"
#include "AudioSegment.h"

namespace mozilla::dom {

struct AudioParamEvent final : public AudioTimelineEvent {
  AudioParamEvent(Type aType, double aTime, float aValue,
                  double aTimeConstant = 0.0)
      : AudioTimelineEvent(aType, aTime, aValue, aTimeConstant) {}
  AudioParamEvent(Type aType, const nsTArray<float>& aValues, double aStartTime,
                  double aDuration)
      : AudioTimelineEvent(aType, aValues, aStartTime, aDuration) {}
  explicit AudioParamEvent(AudioNodeTrack* aTrack)
      : AudioTimelineEvent(Track, 0.0, 0.f), mTrack(aTrack) {}

  RefPtr<AudioNodeTrack> mTrack;
};

// This helper class is used to represent the part of the AudioParam
// class that gets sent to AudioNodeEngine instances.  In addition to
// AudioEventTimeline methods, it holds a pointer to an optional
// AudioNodeTrack which represents the AudioNode inputs to the AudioParam.
// This AudioNodeTrack is managed by the AudioParam subclass on the main
// thread, and can only be obtained from the AudioNodeEngine instances
// consuming this class.
class AudioParamTimeline : public AudioEventTimeline {
  typedef AudioEventTimeline BaseClass;

 public:
  explicit AudioParamTimeline(float aDefaultValue) : BaseClass(aDefaultValue) {}

  AudioNodeTrack* Track() const { return mTrack; }

  bool HasSimpleValue() const {
    return BaseClass::HasSimpleValue() &&
           (!mTrack || mTrack->LastChunks()[0].IsNull());
  }

  template <class TimeType>
  float GetValueAtTime(TimeType aTime);

  // Prefer this method over GetValueAtTime() only if HasSimpleValue() is
  // known false.
  float GetComplexValueAtTime(int64_t aTime);
  float GetComplexValueAtTime(double aTime) = delete;

  template <typename TimeType>
  void InsertEvent(const AudioParamEvent& aEvent) {
    if (aEvent.mType == AudioTimelineEvent::Cancel) {
      CancelScheduledValues(aEvent.Time<TimeType>());
      return;
    }
    if (aEvent.mType == AudioTimelineEvent::Track) {
      mTrack = aEvent.mTrack;
      return;
    }
    if (aEvent.mType == AudioTimelineEvent::SetValue) {
      AudioEventTimeline::SetValue(aEvent.NominalValue());
      return;
    }
    AudioEventTimeline::InsertEvent<TimeType>(aEvent);
  }

  // Get the values of the AudioParam at time aTime + (0 to aSize).
  // aBuffer must have the correct aSize.
  // aSize here is an offset to aTime if we try to get the value in ticks,
  // otherwise it should always be zero.  aSize is meant to be used when
  // getting the value of an a-rate AudioParam for each tick inside an
  // AudioNodeEngine implementation.
  void GetValuesAtTime(int64_t aTime, float* aBuffer, const size_t aSize);
  void GetValuesAtTime(double aTime, float* aBuffer,
                       const size_t aSize) = delete;

  virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
    return mTrack ? mTrack->SizeOfIncludingThis(aMallocSizeOf) : 0;
  }

  virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
  }

 private:
  float AudioNodeInputValue(size_t aCounter) const;

 protected:
  // This is created lazily when needed.
  RefPtr<AudioNodeTrack> mTrack;
};

template <>
inline float AudioParamTimeline::GetValueAtTime(double aTime) {
  // Getting an AudioParam value on an AudioNode does not consider input from
  // other AudioNodes, which is managed only on the graph thread.
  return BaseClass::GetValueAtTime(aTime);
}

template <>
inline float AudioParamTimeline::GetValueAtTime(int64_t aTime) {
  // Use GetValuesAtTime() for a-rate parameters.
  MOZ_ASSERT(aTime % WEBAUDIO_BLOCK_SIZE == 0);
  if (HasSimpleValue()) {
    return GetValue();
  }
  return GetComplexValueAtTime(aTime);
}

inline float AudioParamTimeline::GetComplexValueAtTime(int64_t aTime) {
  MOZ_ASSERT(aTime % WEBAUDIO_BLOCK_SIZE == 0);

  // Mix the value of the AudioParam itself with that of the AudioNode inputs.
  return BaseClass::GetValueAtTime(aTime) +
         (mTrack ? AudioNodeInputValue(0) : 0.0f);
}

inline void AudioParamTimeline::GetValuesAtTime(int64_t aTime, float* aBuffer,
                                                const size_t aSize) {
  MOZ_ASSERT(aBuffer);
  MOZ_ASSERT(aSize <= WEBAUDIO_BLOCK_SIZE);
  MOZ_ASSERT(aSize == 1 || !HasSimpleValue());

  // Mix the value of the AudioParam itself with that of the AudioNode inputs.
  BaseClass::GetValuesAtTime(aTime, aBuffer, aSize);
  if (mTrack) {
    uint32_t blockOffset = aTime % WEBAUDIO_BLOCK_SIZE;
    MOZ_ASSERT(blockOffset + aSize <= WEBAUDIO_BLOCK_SIZE);
    for (size_t i = 0; i < aSize; ++i) {
      aBuffer[i] += AudioNodeInputValue(blockOffset + i);
    }
  }
}

}  // namespace mozilla::dom

#endif