128 if (d->m_paused.loadRelaxed())
131 constexpr auto bufferSize = QAudioEngineThreaded::bufferSize;
133 QMutexLocker l(&d->mutex);
136 int nChannels = ambisonicDecoder ? ambisonicDecoder->nOutputChannels() : 2;
137 if (len < nChannels *
int(
sizeof(
float)) * bufferSize)
140 short *fd = (
short *)data;
141 qint64 frames = len / nChannels /
sizeof(
short);
143 while (frames >= qint64(bufferSize)) {
145 for (
auto *source : std::as_const(d->sources)) {
146 auto *sp = QSpatialSoundPrivate::get(source);
149 float buf[bufferSize];
150 sp->getBuffer(buf, bufferSize, 1);
151 d->resonanceAudio->api->SetInterleavedBuffer(sp->sourceId, buf, 1, bufferSize);
153 for (
auto *source : std::as_const(d->stereoSources)) {
154 auto *sp = QAmbientSoundPrivate::get(source);
157 float buf[2 * bufferSize];
158 sp->getBuffer(buf, bufferSize, 2);
159 d->resonanceAudio->api->SetInterleavedBuffer(sp->sourceId, buf, 2, bufferSize);
162 if (ambisonicDecoder && d->m_outputMode == QAudioEngine::Surround) {
163 const float *channels[QAmbisonicDecoder::maxAmbisonicChannels];
164 const float *reverbBuffers[2];
165 int nSamples = d->resonanceAudio->getAmbisonicOutput(channels, reverbBuffers, ambisonicDecoder->nInputChannels());
166 Q_ASSERT(ambisonicDecoder->nOutputChannels() <= 8);
167 ambisonicDecoder->processBufferWithReverb(channels, reverbBuffers, fd, nSamples);
169 ok = d->resonanceAudio->api->FillInterleavedOutputBuffer(2, bufferSize, fd);
174 if (d->sources.isEmpty() && d->stereoSources.isEmpty()) {
175 memset(fd, 0, nChannels * bufferSize *
sizeof(
short));
178 qWarning() <<
" Reading failed!";
183 fd += nChannels * bufferSize;
184 frames -= bufferSize;
186 const int bytesProcessed = ((
char *)fd - data);
187 m_pos += bytesProcessed;
188 return bytesProcessed;
208 resonanceAudio->api->SetStereoSpeakerMode(m_outputMode != QAudioEngine::Headphone);
209 resonanceAudio->api->SetMasterVolume(masterVolume());
211 outputStream = std::make_unique<QAudioOutputStream>(
this);
212 outputStream->moveToThread(&audioThread);
213 audioThread.start(QThread::TimeCriticalPriority);
215 QMetaObject::invokeMethod(outputStream.get(), &QAudioOutputStream::startOutput);
258 if (m_outputMode == mode)
261 resonanceAudio->api->SetStereoSpeakerMode(mode != QAudioEngine::Headphone);
263 QMetaObject::invokeMethod(outputStream.get(), &QAudioOutputStream::restartOutput,
264 Qt::BlockingQueuedConnection);
267 emit q->outputModeChanged();
348 if (!m_roomEffectsEnabled)
351 bool needUpdate = listenerPositionDirty;
352 listenerPositionDirty =
false;
354 bool roomDirty =
false;
355 for (
const auto &room : std::as_const(rooms)) {
356 auto *rd = QAudioRoomPrivate::get(room);
367 auto inferredRoom = findSmallestRoomForListener(rooms);
368 if (inferredRoom.room != m_currentRoom)
370 const bool previousRoom = m_currentRoom;
371 m_currentRoom = inferredRoom.room;
377 if (!m_currentRoom) {
378 resonanceAudio->api->EnableRoomEffects(
false);
382 resonanceAudio->api->EnableRoomEffects(
true);
384 QAudioRoomPrivate *rp = QAudioRoomPrivate::get(m_currentRoom);
385 resonanceAudio->api->SetReflectionProperties(rp->reflections);
386 resonanceAudio->api->SetReverbProperties(rp->reverb);
389 for (
auto *s : std::as_const(sources)) {
390 auto *sp = QSpatialSoundPrivate::get(s);
393 sp->updateRoomEffects();