2 Skelton for retropc emulator
4 Author : K.Ohta <whatisthis.sowhat _at_ gmail.com>
10 Note: 20220715 K.Ohta : This will be based on QtMultimedia's audio driver,
11 But this still has a lot of delay.Will fix or discard.
12 Quote from "Audio Overview" of Qt6.3.1 's documentation;
13 https://doc.qt.io/qt-6/audiooverview.html
15 The low level audio classes can operate in two modes - push and pull.
16 In pull mode, the audio device is started by giving it a QIODevice.
17 For an output device, the QAudioSink class will pull data from the
18 QIODevice (using QIODevice::read()) when more audio data is required.
19 Conversely, for pull mode with QAudioSource, when audio data is available
20 then the data will be written directly to the QIODevice.
22 In push mode, the audio device provides a QIODevice instance that can be
23 written or read to as needed.
24 Typically, this results in simpler code but more buffering,
25 which may affect latency.
29 #include "../fileio.h"
31 #include "../types/util_sound.h"
32 #include "../types/util_endians.h"
37 //#include "csp_logger.h"
38 #include "gui/menu_flags.h"
47 #include "./sound_buffer_qt.h"
49 void OSD_BASE::audio_capture_callback(void *udata, Uint8 *stream, int len)
52 if(udata == NULL) return;
53 if(stream == NULL) return;
55 osd_snddata_capture_t *pData = (osd_snddata_capture_t *)udata;
57 if(pData->read_buffer_ptr == NULL) return;
58 if((pData->writepos + len) >= pData->buffer_size) {
60 len2 = pData->buffer_size - pData->writepos;
61 if(len2 > len) len2 = len;
62 memset(&(pData->read_buffer_ptr[pData->writepos]), 0x00, len2);
63 memcpy(&(pData->read_buffer_ptr[pData->writepos]), stream, len2);
66 memset(&(pData->read_buffer_ptr[0]), 0x00, len3);
67 memcpy(&(pData->read_buffer_ptr[0]), &(stream[len2]), len3);
71 memset(&(pData->read_buffer_ptr[pData->writepos]), 0x00, len);
72 memcpy(&(pData->read_buffer_ptr[pData->writepos]), stream, len);
74 pData->writepos += len;
75 if(pData->writepos >= pData->buffer_size) {
76 pData->writepos -= pData->buffer_size;
78 pData->writelen += len;
79 if(pData->writelen >= pData->buffer_size) {
80 pData->writelen = pData->buffer_size;
85 void OSD_BASE::audio_callback(void *udata, Uint8 *stream, int len)
88 if(udata == NULL) return;
89 if(stream == NULL) return;
91 sdl_snddata_t *pData = (sdl_snddata_t *)udata;
92 int sndlen, sndpos, bufsize;
97 memset(stream, 0x00, len);
98 switch(pData->sound_format) {
103 format_len = sizeof(int16_t);
107 format_len = sizeof(int32_t);
111 format_len = sizeof(float);
116 if(pData->p_config->general_sound_level < INT16_MIN) pData->p_config->general_sound_level = INT16_MIN;
117 if(pData->p_config->general_sound_level > INT16_MAX) pData->p_config->general_sound_level = INT16_MAX;
118 *pData->snd_total_volume = (uint8_t)(((uint32_t)(pData->p_config->general_sound_level + (-INT16_MIN))) >> 9);
121 sndlen = *(pData->sound_data_len);
122 bufsize = *(pData->sound_buffer_size);
123 sndpos = *(pData->sound_write_pos);
124 if(*pData->sound_exit) {
128 sndpos = sndpos * format_len;
129 sndlen = sndlen * format_len; // ToDo: Multiple format
130 bufsize = bufsize * format_len; // ToDo: Multiple format
132 if(sndlen >= len) sndlen = len;
133 if((sndpos + sndlen) >= bufsize) { // Need to wrap
134 int len2 = bufsize - sndpos;
135 uint8_t* p = (uint8_t *)(*pData->sound_buf_ptr);
136 uint8_t* s = &stream[spos];
138 #if defined(USE_SDL2)
139 SDL_MixAudioFormat(s, p, pData->sound_format, len2, *(pData->snd_total_volume));
141 SDL_MixAudio(s, p, len2, *(pData->snd_total_volume));
144 len2 = sndlen - len2;
146 *(pData->sound_write_pos) = 0;
148 p = (uint8_t *)(*pData->sound_buf_ptr);
150 #if defined(USE_SDL2)
151 SDL_MixAudioFormat(s, p, pData->sound_format, len2, *(pData->snd_total_volume));
153 SDL_MixAudio(s, p, len2, *(pData->snd_total_volume));
155 *(pData->sound_write_pos) = (len2 / format_len);
156 if(*(pData->sound_buffer_size) <= *(pData->sound_write_pos)) {
157 *(pData->sound_write_pos) = 0;
164 } else { // No Need to wrap
166 uint8_t* p = (uint8_t *)(*pData->sound_buf_ptr);
167 uint8_t* s = &stream[spos];
169 #if defined(USE_SDL2)
170 SDL_MixAudioFormat(s, p, pData->sound_format, len2, *(pData->snd_total_volume));
172 SDL_MixAudio(s, p, len2, *(pData->snd_total_volume));
174 *(pData->sound_write_pos) += (len2 / format_len);
175 if(*(pData->sound_buffer_size) <= *(pData->sound_write_pos)) {
176 *(pData->sound_write_pos) = 0;
181 *(pData->sound_data_len) -= (sndlen / format_len);
182 if(*(pData->sound_data_len) <= 0) return;
183 if(spos >= len3) return;
184 // WIP: Do place wait (1ms)?
188 const _TCHAR *OSD_BASE::get_vm_device_name()
190 if(using_flags != NULL) {
191 QString s = using_flags->get_device_name();
192 static QByteArray __n = s.toUtf8();
193 return (const _TCHAR*)(__n.constData());
195 return (const _TCHAR*)"";
199 int OSD_BASE::get_sound_device_num()
201 return sound_device_list.count();
204 const _TCHAR *OSD_BASE::get_sound_device_name(int num)
206 if(num < 0) return NULL;
207 if(num >= sound_device_list.count()) return NULL;
208 QString sdev = sound_device_list.at(num);
210 static QByteArray _n;
212 _n = sdev.toUtf8().constData();
214 return (const _TCHAR*)(_n.constData());
217 void OSD_BASE::get_sound_device_list()
219 sound_device_list.clear();
220 #if defined(USE_SDL2)
221 const _TCHAR* drvname = SDL_GetCurrentAudioDriver();
222 if(drvname == nullptr) return;
223 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Using Sound Driver: %s\n", drvname);
224 for(int i = 0; i < SDL_GetNumAudioDevices(0); i++) {
225 QString tmps = QString::fromUtf8(SDL_GetAudioDeviceName(i, 0));
226 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
227 "Audio Device #%d: %s", i, tmps.toLocal8Bit().constData());
228 sound_device_list.append(tmps);
233 void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* presented_samples)
238 bool pre_initialized = sound_initialized;
239 if(sound_initialized) {
243 sound_capture_device_list.clear();
245 for(int ch = 0 ; ch < MAX_CAPTURE_SOUND; ch++) {
247 // ToDo: Close physical device.
248 if(!pre_initialized) {
249 sound_capturing_emu[ch] = false;
251 sound_capture_desc[ch].physical_dev = 0;
252 sound_capture_desc[ch].read_format = AUDIO_S16SYS;
253 sound_capture_desc[ch].read_rate = 0;
254 sound_capture_desc[ch].read_channels = 0;
255 sound_capture_desc[ch].read_samples = 0;
256 sound_capture_desc[ch].read_silence = 0;
257 sound_capture_desc[ch].read_size = 0;
258 sound_capture_desc[ch].read_userdata = NULL;
259 sound_capture_desc[ch].sample_type = 0; // ToDo : ENUM
260 sound_capture_desc[ch].rate = 0;
261 sound_capture_desc[ch].channels = 0;
262 sound_capture_desc[ch].samples = 0;
263 sound_capture_desc[ch].write_size = 0;
264 sound_capture_desc[ch].write_pos = 0;
265 sound_capture_desc[ch].read_data_len = 0;
266 sound_capture_desc[ch].read_buffer_len = 0;
267 sound_capture_desc[ch].read_buffer_ptr = NULL;
268 sound_capture_desc[ch].out_buffer = NULL;
271 for(int num = 0 ; num < MAX_SOUND_CAPTURE_DEVICES; num++) {
272 sound_capture_dev_desc[num].format = AUDIO_S16SYS;
273 sound_capture_dev_desc[num].sample_rate = 0;
274 sound_capture_dev_desc[num].channels = 0;
275 sound_capture_dev_desc[num].buffer_samples = 0;
276 sound_capture_dev_desc[num].silence = 0;
277 sound_capture_dev_desc[num].size = 0;
278 sound_capture_dev_desc[num].callback = audio_capture_callback;
279 sound_capture_dev_desc[num].userdata.format = AUDIO_S16SYS;
280 sound_capture_dev_desc[num].userdata.buffer_size = 0;
281 sound_capture_dev_desc[num].userdata.readlen = 0;
282 sound_capture_dev_desc[num].userdata.writelen = 0;
283 sound_capture_dev_desc[num].userdata.readpos = 0;
284 sound_capture_dev_desc[num].userdata.read_buffer_ptr = NULL;
285 capturing_sound[num] = false;
290 sound_samples = samples;
291 rec_sound_buffer_ptr = 0;
292 sound_ok = sound_started = now_mute = now_record_sound = false;
295 sound_buffer_size = 0;
299 //sound_debug = true;
300 sound_buf_ptr = NULL;
301 sound_initialized = false;
302 // initialize direct sound
304 snd_total_volume = 127;
306 snddata.sound_buf_ptr = (uint8_t**)(&sound_buf_ptr);
307 snddata.sound_buffer_size = &sound_buffer_size;
308 snddata.sound_write_pos = &sound_write_pos;
309 snddata.sound_data_len = &sound_data_len;
310 snddata.snd_total_volume = &snd_total_volume;
311 snddata.sound_exit = &sound_exit;
312 snddata.sound_debug = &sound_debug;
313 snddata.p_config = p_config;
315 snd_spec_req.format = AUDIO_S16SYS;
316 snd_spec_req.channels = 2;
317 snd_spec_req.freq = sound_rate;
318 //snd_spec_req.samples = ((sound_rate * 100) / 1000);
319 snd_spec_req.samples = samples;
320 snd_spec_req.callback = &(this->audio_callback);
321 snd_spec_req.userdata = (void *)&snddata;
322 #if defined(USE_SDL2)
324 if(!(sound_device_list.isEmpty())) {
326 if(p_config->sound_device_num >= sound_device_list.count()) {
327 p_config->sound_device_num = sound_device_list.count() - 1;
329 if(p_config->sound_device_num <= 0) {
330 p_config->sound_device_num = 0;
332 sdev = sound_device_list.at(p_config->sound_device_num);
333 audio_dev_id = SDL_OpenAudioDevice(sdev.toUtf8().constData(), 0,
334 &snd_spec_req, &snd_spec_presented,
336 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Try to open DEVICE #%d: %s -> %s: DEVID=%d\n",
337 p_config->sound_device_num, sdev.toUtf8().constData(), (audio_dev_id <= 0) ? "FAIL" : "SUCCESS", audio_dev_id);
339 audio_dev_id = SDL_OpenAudioDevice("", 0,
340 &snd_spec_req, &snd_spec_presented,
342 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Try to open DEVICE #%d: %s: DEVID=%d\n",
343 p_config->sound_device_num, (audio_dev_id <= 0) ? "FAIL" : "SUCCESS", audio_dev_id);
348 SDL_OpenAudio(&snd_spec_req, &snd_spec_presented);
351 #if defined(USE_SDL2)
352 if(audio_dev_id <= 0) {
353 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,"Failed to initialize sound\n");
354 if(presented_rate != NULL) {
355 *presented_rate = sound_rate;
357 if(presented_samples != NULL) {
358 *presented_samples = sound_samples;
360 sound_initialized = false;
361 sound_ok = sound_first_half = false;
365 snddata.sound_format = snd_spec_presented.format;
366 if((snd_spec_presented.freq != sound_rate) ||
367 (snd_spec_presented.samples != sound_samples)) { // DEINI
368 sound_rate = snd_spec_presented.freq;
369 sound_samples = snd_spec_presented.samples;
371 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,"Sample rate=%d samples=%d\n", sound_rate, sound_samples);
372 if(presented_rate != NULL) {
373 *presented_rate = sound_rate;
375 if(presented_samples != NULL) {
376 *presented_samples = sound_samples;
380 switch(snddata.sound_format) {
385 format_len = sizeof(int16_t);
389 format_len = sizeof(int32_t);
393 format_len = sizeof(float);
396 sound_buffer_size = sound_samples * snd_spec_presented.channels * 2;
397 sound_buf_ptr = (uint8_t *)malloc(sound_buffer_size * format_len);
398 if(sound_buf_ptr == NULL) {
399 #if defined(USE_SDL2)
400 SDL_CloseAudioDevice(audio_dev_id);
407 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
408 "Sound OK: BufSize = %d", sound_buffer_size);
409 memset(sound_buf_ptr, 0x00, sound_buffer_size * format_len);
410 sound_initialized = true;
411 sound_ok = sound_first_half = true;
414 void OSD_BASE::release_sound()
418 sound_initialized = false;
420 for(int num = 0; num < MAX_SOUND_CAPTURE_DEVICES; num++) {
421 if(capturing_sound[num]) {
422 close_sound_capture_device(num, true);
426 for(int ch = 0; ch < MAX_CAPTURE_SOUNDS; ch++) {
427 if(sound_capturing_emu[ch]) {
428 close_capture_sound_emu(ch);
432 #if defined(USE_SDL2)
433 //SDL_PauseAudioDevice(audio_dev_id, 1);
434 SDL_CloseAudioDevice(audio_dev_id);
439 if(sound_buf_ptr != NULL) free(sound_buf_ptr);
440 sound_buf_ptr = NULL;
445 #include <QtMultimedia>
446 void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* presented_samples)
449 QAudioFormat desired;
450 if(m_audioOutputSink != nullptr) {
451 m_audioOutputSink->stop();
452 delete m_audioOutputSink;
453 m_audioOutputSink = nullptr;
455 desired.setChannelCount(2);
456 desired.setSampleRate(rate);
457 desired.setSampleFormat(QAudioFormat::Int16);
458 desired.setChannelConfig(QAudioFormat::ChannelConfigStereo);
460 bool output_available = false;
461 if(m_audioOutputDevice.isFormatSupported(desired)) {
462 desired = m_audioOutputDevice.preferredFormat();
464 m_audioOutputFormat = desired;
465 m_audioOutputSink = new QAudioSink(m_audioOutputDevice, m_audioOutputFormat, this);
466 //m_audioOutputSink = new QAudioSink(m_audioOutputFormat, this);
468 if(m_audioOutput != nullptr) {
469 if(m_audioOutput->isOpen()) {
470 m_audioOutput->close();
472 delete m_audioOutput;
473 m_audioOutput = nullptr;
475 rate = m_audioOutputFormat.sampleRate();
476 if(rate <= 0) rate = 8000;
477 int wordsize = sizeof(int16_t);
478 switch(m_audioOutputFormat.sampleFormat()) {
479 case QAudioFormat::UInt8:
480 wordsize = sizeof(uint8_t);
482 case QAudioFormat::Int16:
483 wordsize = sizeof(int16_t);
485 case QAudioFormat::Int32:
486 wordsize = sizeof(int32_t);
488 case QAudioFormat::Float:
489 wordsize = sizeof(float);
492 int outbuffer_length = samples * 2;
494 m_audioOutput = new SOUND_BUFFER_QT(samples * 2 * sizeof(int16_t) * 2);
495 if(m_audioOutput != nullptr) {
496 m_audioOutput->open(QIODeviceBase::ReadWrite);
499 sound_samples = samples;
501 // sound_samples = samples;
502 // sound_rate = rate;
503 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,"Sample rate=%d samples=%d\n", sound_rate, sound_samples);
505 rec_sound_buffer_ptr = 0;
506 sound_ok = sound_started = now_mute = now_record_sound = false;
509 sound_buffer_size = 0;
513 //sound_debug = true;
514 sound_buf_ptr = NULL;
516 if(presented_rate != nullptr) {
517 *presented_rate = sound_rate;
519 if(presented_samples != nullptr) {
520 *presented_samples = sound_samples;
524 // if(m_audioOutput != nullptr) {
525 if(m_audioOutputSink != nullptr) {
527 sound_initialized = true;
528 if(p_config != nullptr) {
529 double _ll = (double)(p_config->general_sound_level + INT16_MAX) / 65535.0;
530 m_audioOutputSink->setVolume(_ll);
532 connect(m_audioOutputSink, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State)));
533 //m_audioOutputSink->setBufferSize(1024);
534 //m_audioOutputSink->setBufferSize(sound_samples * 2 * sizeof(int16_t) * 2);
535 m_audioOutput->reset();
536 //m_audioOutputSink->start(m_audioOutput);
537 //m_audioOutputSink->suspend();
540 sound_initialized = false;
541 m_audioOutput = nullptr;
544 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
545 "Sound OK: BufSize = %d", outbuffer_length);
549 void OSD_BASE::release_sound()
552 // release Qt Multimedia sound
554 sound_initialized = false;
555 if(m_audioOutputSink != nullptr) {
556 m_audioOutputSink->stop();
558 while((m_audioOutputSink->state() != QAudio::StoppedState) && (timeout >= 0)) {
559 QThread::usleep(1000); // Wait 1mS
562 delete m_audioOutputSink;
563 m_audioOutputSink = nullptr;
566 if(m_audioOutput != nullptr) {
567 if(m_audioOutput->isOpen()) {
568 m_audioOutput->close();
570 delete m_audioOutput;
571 m_audioOutput = nullptr;
575 sound_initialized = false;
578 void OSD_BASE::do_update_master_volume(int level)
580 QMutexLocker l(vm_mutex);
581 double _ll = (double)(level + INT16_MAX) / 65535.0;
582 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
583 "Set Master Volume to %f .", _ll);
584 if(m_audioOutputSink != nullptr) {
585 m_audioOutputSink->setVolume(_ll);
589 void OSD_BASE::do_set_host_sound_output_device(QString device_name)
591 if(device_name.isEmpty()) return;
592 QString _older = m_audioOutputDevice.description();
593 if(device_name == QString::fromUtf8("Default")) {
594 m_audioOutputDevice = QMediaDevices::defaultAudioOutput();
596 QList<QAudioDevice> devlist = QMediaDevices::audioOutputs();
597 for(auto p = devlist.begin(); p != devlist.end() ; ++p) {
598 if((*p).description() == device_name) {
599 m_audioOutputDevice = *p;
604 QString _newer = m_audioOutputDevice.description();
605 if(_older.compare(_newer) != 0) {
606 QMutexLocker l(vm_mutex);
607 if((p_config != nullptr) && (using_flags != nullptr)) {
608 int freq_val = using_flags->get_sound_sample_rate(p_config->sound_frequency);
609 double latency_val = using_flags->get_sound_latency(p_config->sound_latency);
610 sound_rate = freq_val;
611 sound_samples = (int)((double)sound_rate * latency_val + 0.5);
615 if(sound_initialized) {
616 initialize_sound(sound_rate, sound_samples, &dummy_rate, &dummy_samples);
618 if((dummy_rate != sound_rate) || (dummy_samples != sound_samples)) {
619 sound_rate = dummy_rate;
620 sound_samples = dummy_samples;
625 const _TCHAR *OSD_BASE::get_sound_device_name(int num)
627 if((num < 0) || (num >= sound_device_list.count())) return (const _TCHAR *)nullptr;
629 QString sdev = sound_device_list.at(num);
631 static QByteArray _n;
633 _n = sdev.toUtf8().constData();
635 return (const _TCHAR*)(_n.constData());
638 void OSD_BASE::get_sound_device_list()
640 sound_device_list.clear();
641 QList<QAudioDevice> tmplist = QMediaDevices::audioOutputs();
643 for(auto p = tmplist.begin(); p != tmplist.end(); ++p) {
644 QString tmps = (*p).description().toUtf8();
645 sound_device_list.append(tmps);
646 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
647 "Audio Device #%d: %s", i, tmps.toLocal8Bit().constData());
653 void OSD_BASE::convert_sound_format(uint8_t* dst1, uint8_t* dst2, int16_t* src1, int16_t* src2, int samples1, int samples2)
655 if(dst1 == NULL) return;
656 if(snddata.sound_format == AUDIO_S16SYS) { // Not Convert
657 if((src1 != NULL) && (samples1 > 0)) {
658 my_memcpy(dst1, src1, samples1 * sizeof(int16_t));
660 if((src2 != NULL) && (samples2 > 0) && (dst2 != NULL)) {
661 my_memcpy(dst2, src2, samples2 * sizeof(int16_t));
667 #if defined(__LITTLE_ENDIAN__)
668 uint8_t l, h, h1, h2;
670 uint8_t h2, h1, h, l;
676 switch(snddata.sound_format) {
680 int16_t *q = (int16_t*)src1;
681 int8_t* p = (int8_t*)dst1;
683 for(int i = 0; i < samples1; i++) {
689 if((src2 != NULL) && (dst2 != NULL)) {
690 int16_t *q = (int16_t*)src2;
691 int8_t* p = (int8_t*)dst2;
693 for(int i = 0; i < samples2; i++) {
702 int16_t *q = (int16_t*)src1;
703 uint8_t* p = (uint8_t*)dst1;
705 for(int i = 0; i < samples1; i++) {
712 if((src2 != NULL) && (dst2 != NULL)) {
713 int16_t *q = (int16_t*)src2;
714 uint8_t* p = (uint8_t*)dst2;
716 for(int i = 0; i < samples2; i++) {
726 int16_t *q = (int16_t*)src1;
727 int16_t* p = (int16_t*)dst1;
729 for(int i = 0; i < samples1; i++) {
731 #if defined(__LITTLE_ENDIAN__)
734 p[i] = dat.get_2bytes_le_to();
738 if((src2 != NULL) && (dst2 != NULL)) {
739 int16_t* q = (int16_t*)src2;
740 int16_t* p = (int16_t*)dst2;
742 for(int i = 0; i < samples2; i++) {
744 #if defined(__LITTLE_ENDIAN__)
747 p[i] = dat.get_2bytes_le_to();
754 int16_t* q = (int16_t*)src1;
755 uint16_t* p = (uint16_t*)dst1;
758 for(int i = 0; i < samples1; i++) {
761 #if defined(__LITTLE_ENDIAN__)
765 p[i] = dat.get_2bytes_le_to();
769 if((src2 != NULL) && (dst2 != NULL)) {
770 int16_t* q = (int16_t*)src2;
771 uint16_t* p = (uint16_t*)dst2;
774 for(int i = 0; i < samples2; i++) {
777 #if defined(__LITTLE_ENDIAN__)
781 p[i] = dat.get_2bytes_le_to();
788 int16_t *q = (int16_t*)src1;
789 int16_t* p = (int16_t*)dst1;
791 for(int i = 0; i < samples1; i++) {
793 #if defined(__LITTLE_ENDIAN__)
794 p[i] = dat.get_2bytes_be_to();
800 if((src2 != NULL) && (dst2 != NULL)) {
801 int16_t* q = (int16_t*)src2;
802 int16_t* p = (int16_t*)dst2;
804 for(int i = 0; i < samples2; i++) {
806 #if defined(__LITTLE_ENDIAN__)
807 p[i] = dat.get_2bytes_be_to();
816 int16_t* q = (int16_t*)src1;
817 uint16_t* p = (uint16_t*)dst1;
820 for(int i = 0; i < samples1; i++) {
823 #if defined(__LITTLE_ENDIAN__)
825 p[i] = dat.get_2bytes_be_to();
831 if((src2 != NULL) && (dst2 != NULL)) {
832 int16_t* q = (int16_t*)src2;
833 uint16_t* p = (uint16_t*)dst2;
836 for(int i = 0; i < samples2; i++) {
839 #if defined(__LITTLE_ENDIAN__)
841 p[i] = dat.get_2bytes_be_to();
851 uint32_t* p = (uint32_t*)dst1;
852 int32_t* q = (int32_t*)src1;
853 for(int i = 0; i < samples1; i++) {
856 p[i] = EndianToLittle_DWORD(data);
859 if((src2 != NULL) && (dst2 != NULL)) {
861 uint32_t* p = (uint32_t*)dst2;
862 int32_t* q = (int32_t*)src2;
863 for(int i = 0; i < samples2; i++) {
866 p[i] = EndianToLittle_DWORD(data);
873 uint32_t* p = (uint32_t*)dst1;
874 int32_t* q = (int32_t*)src1;
875 for(int i = 0; i < samples1; i++) {
878 p[i] = EndianToBig_DWORD(data);
881 if((src2 != NULL) && (dst2 != NULL)) {
882 uint32_t* p = (uint32_t*)dst2;
883 int32_t* q = (int32_t*)src2;
885 for(int i = 0; i < samples2; i++) {
888 p[i] = EndianToBig_DWORD(data);
894 uint32_t* p = (uint32_t*)dst1;
895 int32_t* q = (int32_t*)src1;
896 for(int i = 0; i < samples1; i++) {
898 float_data.f /= 65536;
899 p[i] = EndianToLittle_DWORD(float_data.d);
902 if((src2 != NULL) && (dst2 != NULL)) {
903 uint32_t* p = (uint32_t*)dst2;
904 int32_t* q = (int32_t*)src2;
905 for(int i = 0; i < samples2; i++) {
907 float_data.f /= 65536;
908 p[i] = EndianToLittle_DWORD(float_data.d);
914 uint32_t* p = (uint32_t*)dst1;
915 int32_t* q = (int32_t*)src1;
916 for(int i = 0; i < samples1; i++) {
918 float_data.f /= 65536;
919 p[i] = EndianToBig_DWORD(float_data.d);
922 if((src2 != NULL) && (dst2 != NULL)) {
923 uint32_t* p = (uint32_t*)dst2;
924 int32_t* q = (int32_t*)src2;
925 for(int i = 0; i < samples2; i++) {
927 float_data.f /= 65536;
928 p[i] = EndianToBig_DWORD(float_data.d);
935 void OSD_BASE::update_sound(int* extra_frames)
941 uint32_t play_c, size1, size2;
943 uint8_t *ptr1, *ptr2;
946 // check current position
947 play_c = sound_write_pos;
948 if(sound_debug) debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_SOUND,
949 "Called time=%d sound_write_pos=%d\n", osd_timer.elapsed(), play_c);
950 if(!sound_first_half) {
951 if((int)play_c < (sound_buffer_size / 2)) {
956 if((int)play_c >= (sound_buffer_size / 2)) {
959 //offset = sound_buffer_size / 2;
962 // sound buffer must be updated
963 Sint16* sound_buffer = (Sint16 *)this->create_sound(extra_frames);
964 if(now_record_sound || now_record_video) {
965 if(sound_samples > rec_sound_buffer_ptr) {
966 int samples = sound_samples - rec_sound_buffer_ptr;
967 int length = samples * sizeof(int16_t) * 2; // stereo
968 rec_sound_bytes += length;
969 if(now_record_video) {
970 //AGAR_DebugLog(AGAR_LOG_DEBUG, "Push Sound %d bytes\n", length);
971 emit sig_enqueue_audio((int16_t *)(&(sound_buffer[rec_sound_buffer_ptr * 2])), length);
974 if(now_record_sound) {
975 rec_sound_fio->Fwrite(sound_buffer + rec_sound_buffer_ptr * 2, length, 1);
977 //if(now_record_video) {
978 // // sync video recording
979 // static double frames = 0;
980 // static int prev_samples = -1;
981 // static double prev_fps = -1;
982 // double fps = this->vm_frame_rate();
983 // frames = fps * (double)samples / (double)sound_rate;
985 //printf("Wrote %d samples ptr=%d\n", samples, rec_sound_buffer_ptr);
986 rec_sound_buffer_ptr += samples;
987 if(rec_sound_buffer_ptr >= sound_samples) rec_sound_buffer_ptr = 0;
995 if(sound_initialized) {
996 switch(snddata.sound_format) {
1001 format_len = sizeof(int16_t);
1005 format_len = sizeof(int32_t);
1009 format_len = sizeof(float);
1012 ssize = sound_samples * snd_spec_presented.channels;
1013 pos = sound_data_pos;
1015 ptr1 = (uint8_t*)(&sound_buf_ptr[pos * format_len]);
1016 if(pos2 >= sound_buffer_size) {
1017 size1 = sound_buffer_size - pos;
1018 size2 = pos2 - sound_buffer_size;
1019 ptr2 = &sound_buf_ptr[0];
1025 #if defined(USE_SDL2)
1026 SDL_LockAudioDevice(audio_dev_id);
1032 my_memcpy(ptr1, sound_buffer, size1 * format_len);
1034 if((ptr2) && (size2 > 0)) {
1035 my_memcpy(ptr2, &sound_buffer[size1], size2 * format_len);
1038 convert_sound_format(ptr1, ptr2, sound_buffer, &sound_buffer[size1], size1, size2);
1041 sound_data_len = sound_data_len + ssize;
1042 if(sound_data_len >= sound_buffer_size) sound_data_len = sound_buffer_size;
1043 sound_data_pos = sound_data_pos + ssize;
1044 if(sound_data_pos >= sound_buffer_size) sound_data_pos = sound_data_pos - sound_buffer_size;
1045 if(!sound_started) sound_started = true;
1046 #if defined(USE_SDL2)
1047 SDL_UnlockAudioDevice(audio_dev_id);
1051 //SDL_UnlockAudio();
1052 SDL_PauseAudioDevice(audio_dev_id, 0);
1056 // SDL_PauseAudioDevice(audio_dev_id, 0);
1057 sound_first_half = !sound_first_half;
1061 void OSD_BASE::mute_sound()
1063 if(!now_mute && sound_ok) {
1064 // check current position
1065 uint32_t size1, size2;
1067 uint8_t *ptr1, *ptr2;
1072 #if defined(USE_SDL2)
1073 SDL_LockAudioDevice(audio_dev_id);
1078 switch(snddata.sound_format) {
1083 format_len = sizeof(int16_t);
1087 format_len = sizeof(int32_t);
1091 format_len = sizeof(float);
1094 ssize = sound_buffer_size / 2;
1095 pos = sound_data_pos;
1097 ptr1 = &sound_buf_ptr[pos * format_len];
1098 if(pos2 >= sound_buffer_size) {
1099 size1 = sound_buffer_size - pos;
1100 size2 = pos2 - sound_buffer_size;
1101 ptr2 = &sound_buf_ptr[0];
1109 memset(ptr1, 0x00, size1 * format_len);
1111 if((ptr2) && (size2 > 0)){
1112 memset(ptr2, 0x00, size2 * format_len);
1114 sound_data_pos = (sound_data_pos + ssize) % sound_buffer_size;
1115 #if defined(USE_SDL2)
1116 SDL_UnlockAudioDevice(audio_dev_id);
1124 void OSD_BASE::stop_sound()
1126 if(sound_ok && sound_started) {
1127 //sound_exit = true;
1128 #if defined(USE_SDL2)
1129 SDL_PauseAudioDevice(audio_dev_id, 1);
1133 sound_started = false;
1134 //sound_exit = false;
1137 void OSD_BASE::handleStateChanged(QAudio::State newState)
1142 void OSD_BASE::handleStateChanged(QAudio::State newState)
1145 case QAudio::ActiveState:
1146 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, _T("AUDIO:ACTIVE"));
1148 case QAudio::IdleState:
1149 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, _T("AUDIO:IDLE"));
1150 //if(m_audioOutputSink != nullptr) {
1151 // m_audioOutputSink->stop();
1154 case QAudio::StoppedState:
1156 if(m_audioOutput != nullptr) {
1157 if(!(m_audioOutput->isOpen())) {
1158 m_audioOutput->close();
1160 delete m_audioOutput;
1162 if(m_audioOutputBuffer != nullptr) {
1163 m_audioOutput = new QBuffer(m_audioOutInternalBuffer, this);
1164 m_audioOutput->open(QIODeviceBase::ReadWrite);
1165 m_audioOutput->reset();
1166 m_audioOutput->close();
1169 //m_audioOutput = nullptr;
1170 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, _T("AUDIO:STOP"));
1172 case QAudio::SuspendedState:
1173 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, _T("AUDIO:SUSPEND"));
1177 void OSD_BASE::update_sound(int* extra_frames)
1183 //debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Sink->bytesFree() = %d", m_audioOutputSink->bytesFree());
1184 if(!sound_started) {
1185 sound_started = true;
1186 if(m_audioOutput != nullptr) {
1187 if(m_audioOutputSink->state() == QAudio::StoppedState) {
1188 m_audioOutput->reset();
1189 m_audioOutputSink->start(m_audioOutput);
1190 } else if(m_audioOutputSink->state() == QAudio::SuspendedState) {
1191 m_audioOutput->reset();
1192 m_audioOutputSink->resume();
1198 int now_mixed_ptr = 0;
1200 now_mixed_ptr = vm->get_sound_buffer_ptr();
1202 if(now_mixed_ptr < sound_samples) {
1206 int16_t* sound_buffer = (int16_t*)create_sound(extra_frames);
1207 if(now_record_sound || now_record_video) {
1208 if(sound_samples > rec_sound_buffer_ptr) {
1209 int samples = sound_samples - rec_sound_buffer_ptr;
1210 int length = samples * sizeof(int16_t) * 2; // stereo
1211 rec_sound_bytes += length;
1212 if(now_record_video) {
1213 //AGAR_DebugLog(AGAR_LOG_DEBUG, "Push Sound %d bytes\n", length);
1214 emit sig_enqueue_audio((int16_t *)(&(sound_buffer[rec_sound_buffer_ptr * 2])), length);
1217 if(now_record_sound) {
1218 rec_sound_fio->Fwrite(sound_buffer + rec_sound_buffer_ptr * 2, length, 1);
1220 //if(now_record_video) {
1221 // // sync video recording
1222 // static double frames = 0;
1223 // static int prev_samples = -1;
1224 // static double prev_fps = -1;
1225 // double fps = this->vm_frame_rate();
1226 // frames = fps * (double)samples / (double)sound_rate;
1228 //printf("Wrote %d samples ptr=%d\n", samples, rec_sound_buffer_ptr);
1229 rec_sound_buffer_ptr += samples;
1230 if(rec_sound_buffer_ptr >= sound_samples) rec_sound_buffer_ptr = 0;
1233 //if(sound_initialized) return;
1234 if(sound_buffer != nullptr) {
1235 if(m_audioOutput != nullptr) {
1236 int wordsize = sizeof(int32_t);
1237 switch(m_audioOutputFormat.sampleFormat()) {
1238 case QAudioFormat::UInt8:
1239 wordsize = sizeof(uint8_t);
1241 case QAudioFormat::Int16:
1242 wordsize = sizeof(int16_t);
1244 case QAudioFormat::Int32:
1245 wordsize = sizeof(int32_t);
1247 case QAudioFormat::Float:
1248 wordsize = sizeof(float);
1252 //qint64 sound_len = sound_samples * sound_rate * 2 * wordsize;
1253 qint64 sound_len = sound_samples * 2;
1255 int _count = sound_samples * 2;
1256 if(m_audioOutputSink->state() != QAudio::ActiveState) {
1257 m_audioOutput->reset();
1258 if(m_audioOutputSink->state() == QAudio::SuspendedState) {
1259 m_audioOutputSink->resume();
1262 if(m_audioOutputSink->state() != QAudio::StoppedState) {
1263 double _ll = (double)(p_config->general_sound_level + INT16_MAX) / 65535.0;
1264 m_audioOutputSink->setVolume(_ll);
1265 qint64 _result = m_audioOutput->write((const char *)sound_buffer, _count * sizeof(int16_t));
1267 //debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "write_to_buffer: desired=%d wrote=%d", _count * sizeof(int16_t), _result);
1268 // m_audioOutputSink->start(m_audioOutput);
1270 //sound_data_len += _count;
1276 void OSD_BASE::mute_sound()
1278 if(!(now_mute) && (sound_ok)) {
1279 if(m_audioOutputSink != nullptr) {
1280 switch(m_audioOutputSink->state()) {
1281 case QAudio::ActiveState:
1282 case QAudio::IdleState:
1283 m_audioOutputSink->suspend();
1288 if(m_audioOutput != nullptr) {
1289 m_audioOutput->reset();
1296 void OSD_BASE::stop_sound()
1298 if((sound_ok) && (sound_started)) {
1299 if(m_audioOutputSink != nullptr) {
1300 switch(m_audioOutputSink->state()) {
1301 case QAudio::ActiveState:
1302 case QAudio::IdleState:
1303 case QAudio::SuspendedState:
1304 m_audioOutputSink->stop();
1309 if(m_audioOutput != nullptr) {
1310 m_audioOutput->reset();
1317 void OSD_BASE::start_record_sound()
1320 if(!now_record_sound) {
1322 QDateTime nowTime = QDateTime::currentDateTime();
1323 QString tmps = QString::fromUtf8("Sound_Save_emu");
1324 tmps = tmps + get_vm_config_name();
1325 tmps = tmps + QString::fromUtf8("_");
1326 tmps = tmps + nowTime.toString(QString::fromUtf8("yyyy-MM-dd_hh-mm-ss.zzz"));
1327 tmps = tmps + QString::fromUtf8(".wav");
1328 strncpy((char *)sound_file_name, tmps.toLocal8Bit().constData(), sizeof(sound_file_name) - 1);
1330 rec_sound_fio = new FILEIO();
1331 if(rec_sound_fio->Fopen(bios_path(sound_file_name), FILEIO_WRITE_BINARY)) {
1332 // write dummy wave header
1333 write_dummy_wav_header((void *)rec_sound_fio);
1335 rec_sound_bytes = 0;
1336 rec_sound_buffer_ptr = 0;
1337 now_record_sound = true;
1339 // failed to open the wave file
1340 delete rec_sound_fio;
1346 void OSD_BASE::stop_record_sound()
1348 if(now_record_sound) {
1350 if(rec_sound_bytes == 0) {
1351 rec_sound_fio->Fclose();
1352 rec_sound_fio->RemoveFile(sound_file_name);
1354 // update wave header
1355 wav_header_t wav_header;
1356 wav_chunk_t wav_chunk;
1358 if(!set_wav_header(&wav_header, &wav_chunk, 2, snd_spec_presented.freq, 16,
1359 (size_t)(rec_sound_bytes + sizeof(wav_header) + sizeof(wav_chunk)))) {
1361 if(!set_wav_header(&wav_header, &wav_chunk, 2, (uint32_t)(m_audioOutputFormat.sampleRate()), 16,
1362 (size_t)(rec_sound_bytes + sizeof(wav_header) + sizeof(wav_chunk)))) {
1364 delete rec_sound_fio;
1365 now_record_sound = false;
1368 rec_sound_fio->Fseek(0, FILEIO_SEEK_SET);
1369 rec_sound_fio->Fwrite(&wav_header, sizeof(wav_header_t), 1);
1370 rec_sound_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
1371 rec_sound_fio->Fclose();
1373 delete rec_sound_fio;
1374 now_record_sound = false;
1379 void OSD_BASE::restart_record_sound()
1381 bool tmp = now_record_sound;
1382 stop_record_sound();
1384 start_record_sound();
1389 int OSD_BASE::get_sound_rate()
1391 return snd_spec_presented.freq;
1394 int OSD_BASE::get_sound_rate()
1396 return (int)(m_audioOutputFormat.sampleRate());
1400 void OSD_BASE::close_capture_sound_emu(int ch)
1403 if(ch >= MAX_CAPTURE_SOUNDS) return;
1404 if(sound_capture_desc[ch].out_buffer != NULL) {
1405 free(sound_capture_desc[ch].out_buffer);
1407 sound_capture_desc[ch].out_buffer = NULL;
1408 sound_capturing_emu[ch] = false;
1411 void *OSD_BASE::get_capture_sound_buffer(int ch)
1413 if(ch < 0) return NULL;
1414 if(ch >= MAX_CAPTURE_SOUNDS) return NULL;
1415 return sound_capture_desc[ch].out_buffer;
1418 bool OSD_BASE::is_capture_sound_buffer(int ch)
1420 if(ch < 0) return false;
1421 if(ch >= MAX_CAPTURE_SOUNDS) return false;
1422 if(sound_capture_desc[ch].out_buffer == NULL) return false;
1423 return sound_capturing_emu[ch];
1425 void *OSD_BASE::open_capture_sound_emu(int ch, int rate, int channels, int sample_type, int samples, int physical_device_num)
1427 if(ch < 0) return NULL;
1428 if(ch >= MAX_CAPTURE_SOUNDS) return NULL;
1430 close_capture_sound_emu(ch);
1431 sound_capture_desc[ch].rate = rate;
1432 sound_capture_desc[ch].channels = channels;
1433 sound_capture_desc[ch].samples = samples;
1434 sound_capture_desc[ch].sample_type = sample_type;
1435 sound_capture_desc[ch].physical_dev = physical_device_num;
1437 if((physical_device_num >= 0) && (physical_device_num < sound_capture_device_list.count()) && (physical_device_num < MAX_SOUND_CAPTURE_DEVICES)) {
1438 if(!(capturing_sound[physical_device_num])) {
1439 stat = open_sound_capture_device(physical_device_num, (rate < 44100) ? 44100 : rate, (channels > 2) ? channels : 2);
1445 switch(sample_type) {
1446 case SAMPLE_TYPE_UINT8:
1447 case SAMPLE_TYPE_SINT8:
1448 p = malloc(sizeof(uint8_t) * channels * (samples + 100));
1450 case SAMPLE_TYPE_UINT16_BE:
1451 case SAMPLE_TYPE_SINT16_BE:
1452 case SAMPLE_TYPE_UINT16_LE:
1453 case SAMPLE_TYPE_SINT16_LE:
1454 p = malloc(sizeof(uint16_t) * channels * (samples + 100));
1456 case SAMPLE_TYPE_UINT32_BE:
1457 case SAMPLE_TYPE_SINT32_BE:
1458 case SAMPLE_TYPE_UINT32_LE:
1459 case SAMPLE_TYPE_SINT32_LE:
1460 p = malloc(sizeof(uint32_t) * channels * (samples + 100));
1462 case SAMPLE_TYPE_FLOAT_BE:
1463 case SAMPLE_TYPE_FLOAT_LE:
1464 p = malloc(sizeof(float) * channels * (samples + 100));
1468 sound_capture_desc[ch].out_buffer = (uint8_t *)p;
1469 sound_capturing_emu[ch] = true;
1473 bool OSD_BASE::open_sound_capture_device(int num, int req_rate, int req_channels)
1475 if(num < 0) return false;
1476 if(num >= MAX_SOUND_CAPTURE_DEVICES) return false;
1477 if(sound_capture_device_list.count() <= num) return false;
1479 SDL_AudioSpec desired;
1480 req.freq = req_rate;
1481 req.channels = req_channels;
1483 req.format = AUDIO_S16SYS;
1484 req.samples = (sizeof(sound_capture_buffer[num]) / sizeof(int16_t)) / req_channels;
1485 req.callback = &(this->audio_capture_callback);
1486 req.userdata = (void *)(&(sound_capture_dev_desc[num].userdata));
1488 if(!(capturing_sound[num])) {
1489 sound_capture_desc[num].physical_dev = SDL_OpenAudioDevice((const char *)sound_capture_device_list.value(num).toUtf8().constData(), 1, &req, &desired, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
1490 if(sound_capture_desc[num].physical_dev <= 0) {
1491 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,"Failed to initialize sound capture device \"%s\"\n", (const char *)sound_capture_device_list.value(num).toUtf8().constData());
1492 sound_capture_desc[num].physical_dev = -1;
1496 capturing_sound[num] = true;
1497 sound_capture_dev_desc[num].format = desired.format;
1498 sound_capture_dev_desc[num].sample_rate = desired.freq;
1499 sound_capture_dev_desc[num].channels = desired.channels;
1500 sound_capture_dev_desc[num].buffer_samples = desired.samples;
1501 sound_capture_dev_desc[num].size = desired.size;
1502 sound_capture_dev_desc[num].callback = desired.callback;
1503 sound_capture_dev_desc[num].silence = desired.silence;
1504 int buflen = desired.samples * desired.channels;
1505 switch(desired.format) {
1508 buflen = buflen * sizeof(int8_t);
1514 buflen = buflen * sizeof(int16_t);
1518 buflen = buflen * sizeof(int32_t);
1522 buflen = buflen * sizeof(float);
1528 sound_capture_dev_desc[num].userdata.buffer_size = buflen;
1529 sound_capture_dev_desc[num].userdata.format = desired.format;
1530 sound_capture_dev_desc[num].userdata.readlen = 0;
1531 sound_capture_dev_desc[num].userdata.writelen = 0;
1532 sound_capture_dev_desc[num].userdata.readpos = 0;
1533 sound_capture_dev_desc[num].userdata.writepos = 0;
1534 sound_capture_dev_desc[num].userdata.read_buffer_ptr = &(sound_capture_buffer[num][0]);
1535 memset(&(sound_capture_buffer[num][0]), 0x00, buflen);
1537 for(int ch = 0; ch < MAX_SOUND_CAPTURE_DEVICES; ch++) {
1538 if(sound_capture_desc[ch].physical_dev == num) {
1539 sound_capture_desc[ch].read_format = desired.format;
1540 sound_capture_desc[ch].read_rate = desired.freq;
1541 sound_capture_desc[ch].read_silence = desired.silence;
1542 sound_capture_desc[ch].read_size = desired.size;
1543 sound_capture_desc[ch].read_channels = desired.channels;
1544 sound_capture_desc[ch].read_samples = desired.samples;
1545 sound_capture_desc[ch].read_callback = desired.callback;
1546 sound_capture_desc[ch].read_userdata = desired.userdata;
1548 sound_capture_desc[ch].read_pos = 0;
1549 sound_capture_desc[ch].read_data_len = 0;
1550 sound_capture_desc[ch].read_buffer_len = buflen;
1551 sound_capture_desc[ch].read_buffer_ptr = (uint8_t *)(&(sound_capture_buffer[num][0]));
1560 bool OSD_BASE::close_sound_capture_device(int num, bool force)
1562 // ToDo: Check capturing entries
1563 if((capturing_sound[num]) && (sound_capture_desc[num].physical_dev > 0)) {
1564 SDL_CloseAudioDevice(sound_capture_desc[num].physical_dev);