summaryrefslogtreecommitdiffstats
path: root/dom/media/webaudio/AudioParamTimeline.h
blob: 5c1c725c10a4f2f2c8baea4a4ec926af052d08e0 (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
/* -*- 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 {

// 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) {
    return GetValueAtTime(aTime, 0);
  }

  template <typename TimeType>
  void InsertEvent(const AudioTimelineEvent& 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.mValue);
      return;
    }
    AudioEventTimeline::InsertEvent<TimeType>(aEvent);
  }

  // Get the value of the AudioParam at time aTime + aCounter.
  // aCounter here is an offset to aTime if we try to get the value in ticks,
  // otherwise it should always be zero.  aCounter is meant to be used when
  template <class TimeType>
  float GetValueAtTime(TimeType aTime, size_t aCounter);

  // 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.
  template <class TimeType>
  void GetValuesAtTime(TimeType aTime, float* aBuffer, const size_t aSize);

  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, size_t aCounter) {
  MOZ_ASSERT(!aCounter);

  // 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,
                                                size_t aCounter) {
  MOZ_ASSERT(aCounter < WEBAUDIO_BLOCK_SIZE);
  MOZ_ASSERT(!aCounter || !HasSimpleValue());

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

template <>
inline void AudioParamTimeline::GetValuesAtTime(double aTime, float* aBuffer,
                                                const size_t aSize) {
  MOZ_ASSERT(aBuffer);
  MOZ_ASSERT(aSize == 1);

  // Getting an AudioParam value on an AudioNode does not consider input from
  // other AudioNodes, which is managed only on the graph thread.
  *aBuffer = BaseClass::GetValueAtTime(aTime);
}

template <>
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