Common Source Code Project for Qt (a.k.a for FM-7).
リビジョン | caf29988cea57695773bef0505ad8a6d710839ff (tree) |
---|---|
日時 | 2022-07-27 23:24:28 |
作者 | K.Ohta <whatisthis.sowhat@gmai...> |
コミッター | K.Ohta |
[OSD][Qt][SOUND] Use shared_ptr to be robust.
@@ -60,14 +60,19 @@ OSD_BASE::OSD_BASE(USING_FLAGS *p, CSP_Logger *logger) : QObject(0) | ||
60 | 60 | #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) |
61 | 61 | m_audioOutputDevice = QMediaDevices::defaultAudioOutput(); |
62 | 62 | m_audioInputDevice = QMediaDevices::defaultAudioInput(); |
63 | + | |
64 | + m_audioOutputSink.reset(new QAudioSink(m_audioOutputDevice, m_audioOutputDevice.preferredFormat())); | |
65 | + m_audioInputSource.reset(); | |
63 | 66 | #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
64 | 67 | m_audioOutputDevice = QAudioDeviceInfo::defaultOutputDevice(); |
65 | 68 | m_audioInputDevice = QAudioDeviceInfo::defaultInputDevice(); |
69 | + | |
70 | + m_audioOutputSink.reset(new QAudioOutput(m_audioOutputDevice, m_audioOutputDevice->preferredFormat())); | |
71 | + m_audioInputSource.reset(); | |
66 | 72 | #endif |
67 | - m_audioOutputSink = nullptr; | |
68 | - m_audioOutput = nullptr; | |
69 | - m_audioInputSource = nullptr; | |
73 | + m_audioOutputSink->moveToThread(this->thread()); | |
70 | 74 | |
75 | + m_audioOutput = nullptr; | |
71 | 76 | m_audioInput = nullptr; |
72 | 77 | sound_initialized = false; |
73 | 78 | sound_us_before_rendered = 0; |
@@ -13,20 +13,26 @@ | ||
13 | 13 | |
14 | 14 | #include <QList> |
15 | 15 | #include <QObject> |
16 | +#include <QThread> | |
16 | 17 | #include <QString> |
17 | 18 | #include <QStringList> |
18 | 19 | #include <QImage> |
19 | 20 | #include <QAudioFormat> |
20 | 21 | #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) |
21 | 22 | #include <QAudioDevice> |
23 | +#include <QAudioSource> | |
24 | +#include <QAudioSink> | |
22 | 25 | #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
23 | 26 | #include <QAudioDeviceInfo> |
27 | +#include <QAudioInput> | |
28 | +#include <QAudioOutput> | |
24 | 29 | #endif |
25 | 30 | |
26 | 31 | #include <SDL.h> |
27 | 32 | |
28 | 33 | #include <string> |
29 | 34 | #include <list> |
35 | +#include <memory> | |
30 | 36 | |
31 | 37 | #include "../config.h" |
32 | 38 | #define SOCKET_MAX 4 |
@@ -166,13 +172,6 @@ typedef struct { | ||
166 | 172 | } osd_snd_capture_desc_t; |
167 | 173 | |
168 | 174 | |
169 | -#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) | |
170 | -class QAudioSource; | |
171 | -class QAudioSink; | |
172 | -#elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
173 | -class QAudioInput; | |
174 | -class QAudioOutput; | |
175 | -#endif | |
176 | 175 | |
177 | 176 | class SOUND_BUFFER_QT; |
178 | 177 |
@@ -186,16 +185,17 @@ private: | ||
186 | 185 | |
187 | 186 | QAudioFormat m_audioOutputFormat; |
188 | 187 | QAudioFormat m_audioInputFormat; |
188 | + std::shared_ptr<QThread> m_audioOutputThread; | |
189 | 189 | |
190 | 190 | #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) |
191 | - QAudioSink *m_audioOutputSink; | |
192 | - QAudioSource *m_audioInputSource; | |
191 | + std::shared_ptr<QAudioSink> m_audioOutputSink; | |
192 | + std::shared_ptr<QAudioSource> m_audioInputSource; | |
193 | 193 | |
194 | 194 | QAudioDevice m_audioOutputDevice; |
195 | 195 | QAudioDevice m_audioInputDevice; |
196 | 196 | #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
197 | - QAudioOutput *m_audioOutputSink; | |
198 | - QAudioInput *m_audioInputSource; | |
197 | + std::shared_ptr<QAudioOutput> m_audioOutputSink; | |
198 | + std::shared_ptr<QAudioInput> m_audioInputSource; | |
199 | 199 | |
200 | 200 | QAudioDeviceInfo m_audioOutputDevice; |
201 | 201 | QAudioDeviceInfo m_audioInputDevice; |
@@ -452,12 +452,12 @@ void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* | ||
452 | 452 | { |
453 | 453 | // ToDo: Sound Input |
454 | 454 | QAudioFormat desired; |
455 | - if(m_audioOutputSink != nullptr) { | |
456 | - m_audioOutputSink->stop(); | |
457 | - delete m_audioOutputSink; | |
458 | - m_audioOutputSink = nullptr; | |
459 | - sound_us_before_rendered = 0; | |
460 | - } | |
455 | + | |
456 | +// if(m_audioOutputSink->state() != QAudio::StoppedState) { | |
457 | +// m_audioOutputSink->stop(); | |
458 | +// } | |
459 | + sound_us_before_rendered = 0; | |
460 | + | |
461 | 461 | #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) |
462 | 462 | desired.setChannelCount(2); |
463 | 463 | desired.setSampleRate(rate); |
@@ -479,12 +479,15 @@ void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* | ||
479 | 479 | // desired = m_audioOutputDevice.preferredFormat(); |
480 | 480 | // } |
481 | 481 | m_audioOutputFormat = desired; |
482 | + m_audioOutputSink->disconnect(); | |
483 | + | |
482 | 484 | #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) |
483 | - m_audioOutputSink = new QAudioSink(m_audioOutputDevice, m_audioOutputFormat, this); | |
485 | + m_audioOutputSink.reset(new QAudioSink(m_audioOutputDevice, m_audioOutputFormat)); | |
484 | 486 | #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
485 | - m_audioOutputSink = new QAudioOutput(m_audioOutputDevice, m_audioOutputFormat, this); | |
487 | + m_audioOutputSink.reset(new QAudioOutput(m_audioOutputDevice, m_audioOutputDevice->preferredFormat())); | |
486 | 488 | #endif |
487 | - | |
489 | + m_audioOutputSink->moveToThread(this->thread()); | |
490 | + | |
488 | 491 | if(m_audioOutput != nullptr) { |
489 | 492 | if(m_audioOutput->isOpen()) { |
490 | 493 | m_audioOutput->close(); |
@@ -505,21 +508,19 @@ void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* | ||
505 | 508 | m_audioOutput->open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Unbuffered); |
506 | 509 | #endif |
507 | 510 | m_audioOutput->reset(); |
508 | - if(m_audioOutputSink != nullptr) { | |
509 | - #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
510 | - m_audioOutputSink->start(m_audioOutput); | |
511 | - #endif | |
512 | - sound_us_before_rendered = 0; | |
511 | + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) | |
512 | + m_audioOutputSink->start(m_audioOutput); | |
513 | + #endif | |
514 | + sound_us_before_rendered = 0; | |
513 | 515 | #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) |
514 | - debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, | |
515 | - "Sound Device to: %s", | |
516 | - m_audioOutputDevice.description().toLocal8Bit().constData()); | |
516 | + debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, | |
517 | + "Sound Device to: %s", | |
518 | + m_audioOutputDevice.description().toLocal8Bit().constData()); | |
517 | 519 | #else |
518 | - debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, | |
519 | - "Sound Device to: %s", | |
520 | - m_audioOutputDevice.deviceName().toLocal8Bit().constData()); | |
520 | + debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, | |
521 | + "Sound Device to: %s", | |
522 | + m_audioOutputDevice.deviceName().toLocal8Bit().constData()); | |
521 | 523 | #endif |
522 | - } | |
523 | 524 | } |
524 | 525 | |
525 | 526 | sound_samples = samples; |
@@ -545,22 +546,15 @@ void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* | ||
545 | 546 | *presented_samples = sound_samples; |
546 | 547 | } |
547 | 548 | |
548 | - if(m_audioOutputSink != nullptr) { | |
549 | - sound_ok = true; | |
550 | - if(p_config != nullptr) { | |
551 | - double _ll = (double)(p_config->general_sound_level + INT16_MAX) / 65535.0; | |
552 | - m_audioOutputSink->setVolume(_ll); | |
553 | - } | |
554 | - connect(m_audioOutputSink, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleAudioOutputStateChanged(QAudio::State))); | |
555 | - } else { | |
556 | - sound_ok = false; | |
557 | - m_audioOutput = nullptr; | |
558 | - sound_us_before_rendered = 0; | |
549 | + sound_ok = true; | |
550 | + if(p_config != nullptr) { | |
551 | + double _ll = (double)(p_config->general_sound_level + INT16_MAX) / 65535.0; | |
552 | + m_audioOutputSink->setVolume(_ll); | |
559 | 553 | } |
554 | + connect(m_audioOutputSink.get(), SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleAudioOutputStateChanged(QAudio::State))); | |
560 | 555 | sound_initialized = true; |
561 | 556 | debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, |
562 | 557 | "Sound OK: BufSize = %d", outbuffer_length); |
563 | - | |
564 | 558 | } |
565 | 559 | |
566 | 560 | void OSD_BASE::release_sound() |
@@ -569,11 +563,21 @@ void OSD_BASE::release_sound() | ||
569 | 563 | // release Qt Multimedia sound |
570 | 564 | sound_exit = true; |
571 | 565 | sound_initialized = false; |
572 | - if(m_audioOutputSink != nullptr) { | |
573 | - delete m_audioOutputSink; | |
574 | - m_audioOutputSink = nullptr; | |
575 | - } | |
576 | -#if 1 | |
566 | + | |
567 | + m_audioOutputSink->disconnect(); | |
568 | + | |
569 | +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) | |
570 | + m_audioOutputDevice = QMediaDevices::defaultAudioOutput(); | |
571 | + m_audioInputDevice = QMediaDevices::defaultAudioInput(); | |
572 | + | |
573 | + m_audioOutputSink.reset(new QAudioSink(m_audioOutputDevice, m_audioOutputDevice.preferredFormat(), this)); | |
574 | +#else | |
575 | + m_audioOutputDevice = QAudioDeviceInfo::defaultOutputDevice(); | |
576 | + m_audioInputDevice = QAudioDeviceInfo::defaultInputDevice(); | |
577 | + | |
578 | + m_audioOutputSink.reset(new QAudioOutput(m_audioOutputDevice, m_audioOutputDevice.preferredFormat(), this)); | |
579 | +#endif | |
580 | + | |
577 | 581 | if(m_audioOutput != nullptr) { |
578 | 582 | if(m_audioOutput->isOpen()) { |
579 | 583 | m_audioOutput->close(); |
@@ -581,7 +585,7 @@ void OSD_BASE::release_sound() | ||
581 | 585 | delete m_audioOutput; |
582 | 586 | m_audioOutput = nullptr; |
583 | 587 | } |
584 | -#endif | |
588 | + | |
585 | 589 | sound_ok = false; |
586 | 590 | sound_initialized = false; |
587 | 591 | } |
@@ -590,11 +594,10 @@ void OSD_BASE::do_update_master_volume(int level) | ||
590 | 594 | { |
591 | 595 | QMutexLocker l(vm_mutex); |
592 | 596 | double _ll = (double)(level + INT16_MAX) / 65535.0; |
593 | - if(m_audioOutputSink != nullptr) { | |
594 | - m_audioOutputSink->setVolume(_ll); | |
595 | - } | |
597 | + m_audioOutputSink->setVolume(_ll); | |
596 | 598 | } |
597 | 599 | |
600 | + | |
598 | 601 | void OSD_BASE::do_set_host_sound_output_device(QString device_name) |
599 | 602 | { |
600 | 603 | if(device_name.isEmpty()) return; |
@@ -644,9 +647,9 @@ void OSD_BASE::do_set_host_sound_output_device(QString device_name) | ||
644 | 647 | } |
645 | 648 | int dummy_rate; |
646 | 649 | int dummy_samples; |
647 | - if(sound_initialized) { | |
650 | + //if(sound_initialized) { | |
648 | 651 | initialize_sound(sound_rate, sound_samples, &dummy_rate, &dummy_samples); |
649 | - } | |
652 | + //} | |
650 | 653 | if((dummy_rate != sound_rate) || (dummy_samples != sound_samples)) { |
651 | 654 | sound_rate = dummy_rate; |
652 | 655 | sound_samples = dummy_samples; |
@@ -1210,9 +1213,10 @@ void OSD_BASE::update_sound(int* extra_frames) | ||
1210 | 1213 | |
1211 | 1214 | now_mute = false; |
1212 | 1215 | if(sound_ok) { |
1213 | - //debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Sink->bytesFree() = %d", m_audioOutputSink->bytesFree()); | |
1214 | - | |
1215 | - const int64_t sound_us_now = (int64_t)m_audioOutputSink->elapsedUSecs(); | |
1216 | + //debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Sink->bytesFree() = %d", m_audioOutputSink->bytesFree()); | |
1217 | + std::shared_ptr<QAudioSink>sink_ptr = m_audioOutputSink; | |
1218 | + | |
1219 | + const int64_t sound_us_now = (int64_t)(sink_ptr->elapsedUSecs()); | |
1216 | 1220 | const int64_t _period_usec = (((int64_t)sound_samples * (int64_t)10000) / (int64_t)sound_rate) * 100; |
1217 | 1221 | int64_t _diff = sound_us_now - (int64_t)sound_us_before_rendered; |
1218 | 1222 | if((_diff < 0) && ((INT64_MAX - (int64_t)sound_us_before_rendered + 1) <= _period_usec)) { |
@@ -1224,11 +1228,11 @@ void OSD_BASE::update_sound(int* extra_frames) | ||
1224 | 1228 | if(vm != nullptr) { |
1225 | 1229 | now_mixed_ptr = vm->get_sound_buffer_ptr(); |
1226 | 1230 | } |
1227 | - if(now_mixed_ptr < ((sound_samples * 90) / 100)) { | |
1228 | - // Render even emulate 95% of latency when remain seconds is less than 2m Sec. | |
1231 | + if(now_mixed_ptr < ((sound_samples * 98) / 100)) { | |
1232 | + // Render even emulate 98% of latency when remain seconds is less than 2m Sec. | |
1229 | 1233 | return; |
1230 | 1234 | } |
1231 | - if((sound_started) && (_diff < (_period_usec - 1000))) { | |
1235 | + if((sound_started) && (_diff < (_period_usec - 2000))) { | |
1232 | 1236 | return; |
1233 | 1237 | } |
1234 | 1238 | qint64 left = 0; |
@@ -1240,12 +1244,13 @@ void OSD_BASE::update_sound(int* extra_frames) | ||
1240 | 1244 | return; |
1241 | 1245 | } |
1242 | 1246 | // Input |
1243 | - int16_t* sound_buffer = (int16_t*)create_sound(extra_frames); | |
1247 | + int16_t* sound_buffer = (int16_t*)create_sound(extra_frames); | |
1248 | + | |
1244 | 1249 | if(sound_buffer != nullptr) { |
1245 | 1250 | if(!(sound_started)) { |
1246 | 1251 | m_audioOutput->reset(); |
1247 | - #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) | |
1248 | - m_audioOutputSink->start(m_audioOutput); | |
1252 | + #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) | |
1253 | + sink_ptr->start(m_audioOutput); | |
1249 | 1254 | #endif |
1250 | 1255 | |
1251 | 1256 | } |
@@ -1287,7 +1292,7 @@ void OSD_BASE::update_sound(int* extra_frames) | ||
1287 | 1292 | int _count = sound_samples * 2; |
1288 | 1293 | |
1289 | 1294 | qint64 _result = m_audioOutput->write((const char *)sound_buffer, _count * sizeof(int16_t)); |
1290 | - sound_us_before_rendered = m_audioOutputSink->elapsedUSecs(); | |
1295 | + sound_us_before_rendered = sink_ptr->elapsedUSecs(); | |
1291 | 1296 | } |
1292 | 1297 | } |
1293 | 1298 | } |
@@ -1296,19 +1301,17 @@ void OSD_BASE::update_sound(int* extra_frames) | ||
1296 | 1301 | void OSD_BASE::mute_sound() |
1297 | 1302 | { |
1298 | 1303 | if(!(now_mute) && (sound_ok)) { |
1299 | - if(m_audioOutputSink != nullptr) { | |
1300 | - switch(m_audioOutputSink->state()) { | |
1301 | - case QAudio::ActiveState: | |
1302 | - case QAudio::IdleState: | |
1303 | - m_audioOutputSink->suspend(); | |
1304 | - break; | |
1305 | - default: | |
1306 | - break; | |
1307 | - } | |
1308 | - if(m_audioOutput != nullptr) { | |
1309 | - m_audioOutput->reset(); | |
1310 | - } | |
1311 | - | |
1304 | + std::shared_ptr<QAudioSink>sink_ptr = m_audioOutputSink; | |
1305 | + switch(sink_ptr->state()) { | |
1306 | + case QAudio::ActiveState: | |
1307 | + case QAudio::IdleState: | |
1308 | + sink_ptr->suspend(); | |
1309 | + break; | |
1310 | + default: | |
1311 | + break; | |
1312 | + } | |
1313 | + if(m_audioOutput != nullptr) { | |
1314 | + m_audioOutput->reset(); | |
1312 | 1315 | } |
1313 | 1316 | } |
1314 | 1317 | now_mute = true; |
@@ -1316,19 +1319,18 @@ void OSD_BASE::mute_sound() | ||
1316 | 1319 | void OSD_BASE::stop_sound() |
1317 | 1320 | { |
1318 | 1321 | if((sound_ok) && (sound_started)) { |
1319 | - if(m_audioOutputSink != nullptr) { | |
1320 | - switch(m_audioOutputSink->state()) { | |
1321 | - case QAudio::ActiveState: | |
1322 | - case QAudio::IdleState: | |
1323 | - case QAudio::SuspendedState: | |
1324 | - m_audioOutputSink->stop(); | |
1325 | - break; | |
1326 | - default: | |
1327 | - break; | |
1328 | - } | |
1329 | - if(m_audioOutput != nullptr) { | |
1330 | - m_audioOutput->reset(); | |
1331 | - } | |
1322 | + std::shared_ptr<QAudioSink>sink_ptr = m_audioOutputSink; | |
1323 | + switch(sink_ptr->state()) { | |
1324 | + case QAudio::ActiveState: | |
1325 | + case QAudio::IdleState: | |
1326 | + case QAudio::SuspendedState: | |
1327 | + sink_ptr->stop(); | |
1328 | + break; | |
1329 | + default: | |
1330 | + break; | |
1331 | + } | |
1332 | + if(m_audioOutput != nullptr) { | |
1333 | + m_audioOutput->reset(); | |
1332 | 1334 | } |
1333 | 1335 | } |
1334 | 1336 | } |