36QSpatialSound::QSpatialSound(QAudioEngine *engine) : QObject(*
new QSpatialSoundPrivate(engine))
40 auto *ep = QAudioEnginePrivate::get(d->engine);
42 ep->addSpatialSound(
this);
43 ep->resonanceAudio->api->SetSourcePosition(d->sourceId, d->pos.x(), d->pos.y(), d->pos.z());
44 ep->resonanceAudio->api->SetSourceRotation(d->sourceId, d->rotation.x(), d->rotation.y(), d->rotation.z(), d->rotation.scalar());
46 ep->resonanceAudio->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder);
47 ep->resonanceAudio->api->SetSoundObjectNearFieldEffectGain(d->sourceId, d->nearFieldGain);
48 d->updateDistanceModel();
209 if (!engine || sourceId < 0)
211 auto *ep = QAudioEnginePrivate::get(engine);
212 if (!ep->currentRoom())
214 auto *rp = QAudioRoomPrivate::get(ep->currentRoom());
218 auto listenerPos = ep->listenerPosition();
222 QVector3D roomDim2 = ep->currentRoom()->dimensions() / 2.;
223 QVector3D roomPos = ep->currentRoom()->position();
224 QQuaternion roomRot = ep->currentRoom()->rotation();
225 QVector3D dist = pos - roomPos;
227 dist = roomRot.rotatedVector(dist);
228 if (qAbs(dist.x()) <= roomDim2.x() &&
229 qAbs(dist.y()) <= roomDim2.y() &&
230 qAbs(dist.z()) <= roomDim2.z()) {
232 ep->resonanceAudio->api->SetSourceRoomEffectsGain(sourceId, 1);
241 auto relativeListenerPos = *listenerPos - roomPos;
242 relativeListenerPos = roomRot.rotatedVector(relativeListenerPos);
244 auto direction = dist.normalized();
250 const float transitionDistance =
size + 0.4;
251 std::array<QAudioRoom::Wall, 3> walls;
252 walls[X] = direction.x() > 0 ? QAudioRoom::RightWall : QAudioRoom::LeftWall;
253 walls[Y] = direction.y() > 0 ? QAudioRoom::FrontWall : QAudioRoom::BackWall;
254 walls[Z] = direction.z() > 0 ? QAudioRoom::Ceiling : QAudioRoom::Floor;
255 std::array<
float, 3> factors = {};
256 bool foundWall =
false;
257 if (direction.x() != 0) {
258 float sign = direction.x() > 0 ? 1.f : -1.f;
259 float dx = sign * roomDim2.x() - relativeListenerPos.x();
260 QVector3D intersection = relativeListenerPos + direction*dx/direction.x();
261 float dy = roomDim2.y() - qAbs(intersection.y());
262 float dz = roomDim2.z() - qAbs(intersection.z());
263 if (dy > 0 && dz > 0) {
266 factors[Y] = qMax(0.f, 1.f/3.f - dy/transitionDistance);
267 factors[Z] = qMax(0.f, 1.f/3.f - dz/transitionDistance);
268 factors[X] = 1.f - factors[Y] - factors[Z];
272 if (!foundWall && direction.y() != 0) {
273 float sign = direction.y() > 0 ? 1.f : -1.f;
274 float dy = sign * roomDim2.y() - relativeListenerPos.y();
275 QVector3D intersection = relativeListenerPos + direction*dy/direction.y();
276 float dx = roomDim2.x() - qAbs(intersection.x());
277 float dz = roomDim2.z() - qAbs(intersection.z());
278 if (dx > 0 && dz > 0) {
281 factors[X] = qMax(0.f, 1.f/3.f - dx/transitionDistance);
282 factors[Z] = qMax(0.f, 1.f/3.f - dz/transitionDistance);
283 factors[Y] = 1.f - factors[X] - factors[Z];
288 Q_ASSERT(direction.z() != 0);
289 float sign = direction.z() > 0 ? 1.f : -1.f;
290 float dz = sign * roomDim2.z() - relativeListenerPos.z();
291 QVector3D intersection = relativeListenerPos + direction*dz/direction.z();
292 float dx = roomDim2.x() - qAbs(intersection.x());
293 float dy = roomDim2.y() - qAbs(intersection.y());
294 if (dx > 0 && dy > 0) {
297 factors[X] = qMax(0.f, 1.f/3.f - dx/transitionDistance);
298 factors[Y] = qMax(0.f, 1.f/3.f - dy/transitionDistance);
299 factors[Z] = 1.f - factors[X] - factors[Y];
305 for (
int i = 0; i < 3; ++i) {
311 ep->resonanceAudio->api->SetSourceRoomEffectsGain(sourceId, 0);
314 ep->resonanceAudio->api->SetSourceVolume(sourceId, volume() *
wallDampening);
446void QSpatialSound::setDirectivity(
float alpha)
450 alpha = qBound(0., alpha, 1.);
451 if (alpha == d->directivity)
453 d->directivity = alpha;
455 auto *ep = QAudioEnginePrivate::get(d->engine);
457 ep->resonanceAudio->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder);
459 emit directivityChanged();