123 if (d->m_paused.loadRelaxed())
126 constexpr auto framesPerBuffer = QAudioEngineThreaded::framesPerBuffer;
127 QSpan<
short> outputBuffer((
short *)data, len /
sizeof(
short));
129 QMutexLocker l(&d->mutex);
132 int nChannels = ambisonicDecoder ? ambisonicDecoder->nOutputChannels() : 2;
133 if (outputBuffer.size() < nChannels * framesPerBuffer)
136 using QtMultimediaPrivate::drop;
137 using QtMultimediaPrivate::take;
140 while (outputBuffer.size() >= nChannels * framesPerBuffer) {
142 for (
auto *source : std::as_const(d->sources)) {
143 auto *sp = QSpatialSoundPrivate::get(source);
146 std::array<
float, framesPerBuffer> buf;
147 sp->getBuffer(buf, framesPerBuffer, 1);
148 d->resonanceAudio->api->SetInterleavedBuffer(sp->sourceId, buf.data(), 1,
151 for (
auto *source : std::as_const(d->stereoSources)) {
152 auto *sp = QAmbientSoundPrivate::get(source);
155 std::array<
float, 2 * framesPerBuffer> buf;
156 sp->getBuffer(buf, framesPerBuffer, 2);
157 d->resonanceAudio->api->SetInterleavedBuffer(sp->sourceId, buf.data(), 2,
161 if (ambisonicDecoder && d->m_outputMode == QAudioEngine::Surround) {
162 std::array<
const float *, QAmbisonicDecoder::maxAmbisonicChannels> channels;
163 std::array<
const float *, 2> reverbBuffers{};
164 int nSamples = d->resonanceAudio->getAmbisonicOutput(
165 channels.data(), reverbBuffers.data(), ambisonicDecoder->nInputChannels());
171 std::fill(outputBuffer.begin(), outputBuffer.end(), 0);
175 Q_ASSERT(ambisonicDecoder->nOutputChannels() <= 8);
176 QSpan<
short> currentOutput = take(outputBuffer, ambisonicDecoder->outputSize(nSamples));
177 ambisonicDecoder->processBufferWithReverb(
178 QSpan{ channels.data(), ambisonicDecoder->nInputChannels() }, reverbBuffers,
180 outputBuffer = drop(outputBuffer, ambisonicDecoder->outputSize(nSamples));
182 QSpan<
short> currentOutput = take(outputBuffer, nChannels * framesPerBuffer);
183 ok = d->resonanceAudio->api->FillInterleavedOutputBuffer(2, framesPerBuffer,
184 currentOutput.data());
189 if (d->sources.isEmpty() && d->stereoSources.isEmpty()) {
190 std::fill(currentOutput.begin(), currentOutput.end(), 0);
193 qWarning() <<
" Reading failed!";
197 outputBuffer = drop(outputBuffer, nChannels * framesPerBuffer);
201 qint64 bytesProcessed = len - outputBuffer.size_bytes();
202 m_pos += bytesProcessed;
203 return bytesProcessed;
223 resonanceAudio->api->SetStereoSpeakerMode(m_outputMode != QAudioEngine::Headphone);
224 resonanceAudio->api->SetMasterVolume(masterVolume());
226 outputStream = std::make_unique<QAudioOutputStream>(
this);
227 outputStream->moveToThread(&audioThread);
228 audioThread.start(QThread::TimeCriticalPriority);
230 QMetaObject::invokeMethod(outputStream.get(), &QAudioOutputStream::startOutput);
360 if (!m_roomEffectsEnabled)
363 bool needUpdate = listenerPositionDirty;
364 listenerPositionDirty =
false;
366 bool roomDirty =
false;
367 for (
const auto &room : std::as_const(rooms)) {
368 auto *rd = QAudioRoomPrivate::get(room);
379 auto inferredRoom = findSmallestRoomForListener(rooms);
380 if (inferredRoom.room != m_currentRoom)
382 const bool previousRoom = m_currentRoom;
383 m_currentRoom = inferredRoom.room;
389 if (!m_currentRoom) {
390 resonanceAudio->api->EnableRoomEffects(
false);
394 resonanceAudio->api->EnableRoomEffects(
true);
396 QAudioRoomPrivate *rp = QAudioRoomPrivate::get(m_currentRoom);
397 resonanceAudio->api->SetReflectionProperties(rp->reflections);
398 resonanceAudio->api->SetReverbProperties(rp->reverb);
401 for (
auto *s : std::as_const(sources)) {
402 auto *sp = QSpatialSoundPrivate::get(s);
405 sp->updateRoomEffects();