This URL has Read-Only access.

Statistics
| Branch: | Tag: | Revision:

root / src / connection.cpp @ a733dd00

History | View | Annotate | Download (5.9 kB)

1
/*
2
 * This file is part of Spatosc.
3
 *
4
 * Copyright (c) 2010 Society for Arts and Technologies <info@sat.qc.ca>
5
 *
6
 * Spatosc is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * Spatosc is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with Spatosc.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
#include "connection.h"
21
#include "soundsource.h"
22
#include "oscutils.h"
23
#include "listener.h"
24
#include <iostream>
25

    
26
namespace spatosc
27
{
28

    
29
double Connection::defaultDistanceFactor = 100.0;
30
double Connection::defaultDopplerFactor = 100.0;
31
double Connection::defaultRolloffFactor = 100.0;
32

    
33
Connection::Connection(SoundSource *source, Listener *sink) :
34
    id_(source->getID() + "->" + sink->getID()),
35
    src_(source),
36
    snk_(sink),
37
    aed_(),
38
    gain_(0.0),
39
    gainDB_(0.0),
40
    vdel_(0.0),
41
    distanceFactor_(Connection::defaultDistanceFactor),
42
    rolloffFactor_(Connection::defaultDopplerFactor),
43
    dopplerFactor_(Connection::defaultRolloffFactor)
44
{
45
    // calculate and store distance, azimuth and elevation
46
    recomputeConnection();
47
}
48

    
49
Connection::~Connection()
50
{
51
    // TODO: there is no pointer to scene_ available, so this has now been
52
    // moved into the scene::disconnect method. It would be better to have it
53
    // here because there are several ways to disconnect things.
54
    //scene_.onSceneChanged("sss", "disconnect", src_->getID().c_str(), snk_->getID().c_str(), SPATOSC_ARGS_END);
55
}
56

    
57
void Connection::recomputeConnection()
58
{
59
        if (active())
60
        {
61
                Vector3 connVec = src_->getPosition() - snk_->getPosition();
62
                //Vector3 snkDir = snk_->getOrientation() * Vector3(0.0, 1.0, 0.0);
63

    
64
                // Rotate connVec by the negative of the rotation described by the snk's
65
                // orientation. To do this, just flip the sign of the quat.w:
66
                Quaternion negRot = snk_->getOrientation();
67
                negRot.w *= -1;
68
                Vector3 rotConnVec = negRot * connVec;
69
                aed_ = cartesianToSpherical(rotConnVec);
70

    
71
                /*
72
                std::cout << "src: "<<src_->getPosition() << ", snk: "<<snk_->getPosition() << std::endl;
73
                std::cout << "snkOrient = " << snk_->getOrientation() << std::endl;
74
                std::cout << "snkDir  = " << snkDir << std::endl;
75
                std::cout << "rotConnVec: "<<rotConnVec << ", length=" << distance() << std::endl;
76
                std::cout << "AED: " << azimuth()*TO_DEGREES <<","<< elevation()*TO_DEGREES <<","<< distance() << std::endl;
77
                Quaternion q = RotationBetweenVectors(snkDir,connVec);
78
                std::cout << "QuatToEuler? = " << QuatToEuler(q)*TO_DEGREES << std::endl;
79
                */
80

    
81
        // the distance() function returns the true distance, but for the gain
82
        // and vdel calculation, we want the distance to the radius:
83
        double dist = distance() - src_->getRadius();
84
        
85
        if (dist>0)
86
        {
87
                    // now from distance, compute gain and variable delay:
88
                    double distanceScalar = 1 / (1.0 + pow(dist, static_cast<double>(distanceFactor_) * 0.01));
89
                    vdel_ = dist * (1 / SPEED_OF_SOUND) * .01 * dopplerFactor_;
90
                    gainDB_ = 20 * log10(distanceScalar);
91
        }
92
        else
93
        {
94
                    vdel_ = 0.0;
95
                    gainDB_ = 0.0;
96
            }
97
    }
98

    
99
        else
100
        {
101
                // when connection is not active (ie, one of the nodes has been
102
                // deactivated, we set the gain to silence (-inf, so -100)
103
                gainDB_ = -100;
104
        }
105

    
106
}
107

    
108
void Connection::setDistanceFactor(double f)
109
{
110
        if (f<0) f = 0.0;
111
        distanceFactor_ = f;
112
        recomputeConnection();
113
}
114

    
115
void Connection::setDopplerFactor(double f)
116
{
117
        if (f<0) f = 0.0;
118
        dopplerFactor_ = f;
119
        recomputeConnection();
120
}
121

    
122
void Connection::setRolloffFactor(double f)
123
{
124
        if (f<0) f = 0.0;
125
        rolloffFactor_ = f;
126
        recomputeConnection();
127
}
128

    
129
void Connection::mute()
130
{
131
        gainDB_ = -100;
132
}
133

    
134
void Connection::unmute()
135
{
136

    
137
}
138

    
139
bool Connection::active() const
140
{
141
    return src_->active() && snk_->active();
142
}
143

    
144
void Connection::debugPrint() const
145
{
146
    std::cout << "  Connection " << id_ << ":" << std::endl;
147
    std::cout << "    azim,elev:\t" << aed_.x*TO_DEGREES <<","<< aed_.y*TO_DEGREES << std::endl;
148
    std::cout << "    distance:\t" << aed_.z << std::endl;
149
    std::cout << "    gain:\t" << gainDB_ << "dB" << std::endl;
150
    std::cout << "    delay:\t" << vdel_ << "ms" << std::endl;
151
    std::cout << "    distanceFactor:\t" << distanceFactor_ << "%" << std::endl;
152
    std::cout << "    rolloffFactor:\t" << rolloffFactor_ << "%" << std::endl;
153
    std::cout << "    dopplerFactor:\t" << dopplerFactor_ << "%" << std::endl;
154
}
155

    
156
// TODO: need to provide types as well
157
void Connection::handleMessage(const std::string &method, lo_arg **argv, const char *types)
158
{
159
    using namespace OSCutil; // typeTagsMatch
160
    if (method == "aed")
161
    {
162
        if (typeTagsMatch(types, "fff"))
163
        {
164
            aed_.x = argv[0]->f;
165
            aed_.y = argv[1]->f;
166
            aed_.z = argv[2]->f;
167
        }
168
    }
169
    else if (method == "delay")
170
    {
171
        if (typeTagsMatch(types, "f"))
172
            vdel_ = argv[0]->f;
173
    }
174
    else if (method == "gain")
175
    {
176
        if (typeTagsMatch(types, "f"))
177
            gain_ = argv[0]->f;
178
    }
179
    else if (method == "gainDB")
180
    {
181
        if (typeTagsMatch(types, "f"))
182
            gainDB_ = argv[0]->f;
183
    }
184
    // FIXME: need types!
185
    /*
186
       else if (method == "setDistanceFactor")
187
       {
188
       if (typeTagsMatch(types, "f")) setDistanceFactor(argv[0]->f);
189
       }
190
       else if (method == "setDopplerFactor")
191
       {
192
       if (typeTagsMatch(types, "f")) setDopplerFactor(argv[0]->f);
193
       }
194
       else if (method == "setRolloffFactor")
195
       {
196
       if (typeTagsMatch(types, "f")) setRolloffFactor(argv[0]->f);
197
       }
198
     */
199
       else
200
           std::cerr << "Unknown method " << method << std::endl;
201
}
202

    
203
} // end namespace spatosc