summaryrefslogtreecommitdiffstats
path: root/dom/media/webaudio/AudioListener.cpp
blob: b8c4e9bc65558e3db544b8fd552b4d22090a5d85 (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
/* -*- 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 "AudioContext.h"
#include "AudioListener.h"
#include "MediaTrackGraph.h"
#include "Tracing.h"
#include "mozilla/dom/AudioListenerBinding.h"

namespace mozilla::dom {

NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AudioListener, mContext)

AudioListenerEngine::AudioListenerEngine()
    : mFrontVector(0., 0., -1.), mRightVector(1., 0., 0.) {}

void AudioListenerEngine::RecvListenerEngineEvent(
    AudioListenerEngine::AudioListenerParameter aParameter,
    const ThreeDPoint& aValue) {
  switch (aParameter) {
    case AudioListenerParameter::POSITION:
      mPosition = aValue;
      break;
    case AudioListenerParameter::FRONT:
      mFrontVector = aValue;
      break;
    case AudioListenerParameter::RIGHT:
      mRightVector = aValue;
      break;
    default:
      MOZ_CRASH("Not handled");
  }
}

const ThreeDPoint& AudioListenerEngine::Position() const { return mPosition; }
const ThreeDPoint& AudioListenerEngine::FrontVector() const {
  return mFrontVector;
}
const ThreeDPoint& AudioListenerEngine::RightVector() const {
  return mRightVector;
}

AudioListener::AudioListener(AudioContext* aContext)
    : mContext(aContext),
      mEngine(new AudioListenerEngine()),

      mFrontVector(0., 0., -1.),
      mRightVector(1., 0., 0.) {
  MOZ_ASSERT(aContext);
}

JSObject* AudioListener::WrapObject(JSContext* aCx,
                                    JS::Handle<JSObject*> aGivenProto) {
  return AudioListener_Binding::Wrap(aCx, this, aGivenProto);
}

void AudioListener::SetOrientation(double aX, double aY, double aZ, double aXUp,
                                   double aYUp, double aZUp) {
  ThreeDPoint front(aX, aY, aZ);
  // The panning effect and the azimuth and elevation calculation in the Web
  // Audio spec becomes undefined with linearly dependent vectors, so keep
  // existing state in these situations.
  if (front.IsZero()) {
    return;
  }
  // Normalize before using CrossProduct() to avoid overflow.
  front.Normalize();
  ThreeDPoint up(aXUp, aYUp, aZUp);
  if (up.IsZero()) {
    return;
  }
  up.Normalize();
  ThreeDPoint right = front.CrossProduct(up);
  if (right.IsZero()) {
    return;
  }
  right.Normalize();

  if (!mFrontVector.FuzzyEqual(front)) {
    mFrontVector = front;
    SendListenerEngineEvent(AudioListenerEngine::AudioListenerParameter::FRONT,
                            mFrontVector);
  }
  if (!mRightVector.FuzzyEqual(right)) {
    mRightVector = right;
    SendListenerEngineEvent(AudioListenerEngine::AudioListenerParameter::RIGHT,
                            mRightVector);
  }
}

void AudioListener::SetPosition(double aX, double aY, double aZ) {
  if (WebAudioUtils::FuzzyEqual(mPosition.x, aX) &&
      WebAudioUtils::FuzzyEqual(mPosition.y, aY) &&
      WebAudioUtils::FuzzyEqual(mPosition.z, aZ)) {
    return;
  }
  mPosition.x = aX;
  mPosition.y = aY;
  mPosition.z = aZ;
  SendListenerEngineEvent(AudioListenerEngine::AudioListenerParameter::POSITION,
                          mPosition);
}

void AudioListener::SendListenerEngineEvent(
    AudioListenerEngine::AudioListenerParameter aParameter,
    const ThreeDPoint& aValue) {
  mContext->DestinationTrack()->QueueControlMessageWithNoShutdown(
      [engine = RefPtr(Engine()), aParameter, aValue] {
        TRACE("AudioListener::RecvListenerEngineEvent");
        engine->RecvListenerEngineEvent(aParameter, aValue);
      });
}

size_t AudioListener::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
  return aMallocSizeOf(this);
}

}  // namespace mozilla::dom