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 "gui/menu_flags.h"
42 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
43 #include <QApplication>
48 #include "./sound-drivers/sound_buffer_qt.h"
49 #include "./sound-drivers/osd_sound_mod_template.h"
51 #include "../gui/emu_thread_tmpl.h"
53 int OSD_BASE::get_sound_device_num()
55 return sound_device_list.count();
57 /* SDL DRIVER: Temporally disabled */
59 void OSD_BASE::audio_capture_callback(void *udata, Uint8 *stream, int len)
62 if(udata == NULL) return;
63 if(stream == NULL) return;
65 osd_snddata_capture_t *pData = (osd_snddata_capture_t *)udata;
67 if(pData->read_buffer_ptr == NULL) return;
68 if((pData->writepos + len) >= pData->buffer_size) {
70 len2 = pData->buffer_size - pData->writepos;
71 if(len2 > len) len2 = len;
72 memset(&(pData->read_buffer_ptr[pData->writepos]), 0x00, len2);
73 memcpy(&(pData->read_buffer_ptr[pData->writepos]), stream, len2);
76 memset(&(pData->read_buffer_ptr[0]), 0x00, len3);
77 memcpy(&(pData->read_buffer_ptr[0]), &(stream[len2]), len3);
81 memset(&(pData->read_buffer_ptr[pData->writepos]), 0x00, len);
82 memcpy(&(pData->read_buffer_ptr[pData->writepos]), stream, len);
84 pData->writepos += len;
85 if(pData->writepos >= pData->buffer_size) {
86 pData->writepos -= pData->buffer_size;
88 pData->writelen += len;
89 if(pData->writelen >= pData->buffer_size) {
90 pData->writelen = pData->buffer_size;
95 void OSD_BASE::audio_callback(void *udata, Uint8 *stream, int len)
98 if(udata == NULL) return;
99 if(stream == NULL) return;
101 sdl_snddata_t *pData = (sdl_snddata_t *)udata;
102 int sndlen, sndpos, bufsize;
107 memset(stream, 0x00, len);
108 switch(pData->sound_format) {
113 format_len = sizeof(int16_t);
117 format_len = sizeof(int32_t);
121 format_len = sizeof(float);
126 if(pData->p_config->general_sound_level < INT16_MIN) pData->p_config->general_sound_level = INT16_MIN;
127 if(pData->p_config->general_sound_level > INT16_MAX) pData->p_config->general_sound_level = INT16_MAX;
128 *pData->snd_total_volume = (uint8_t)(((uint32_t)(pData->p_config->general_sound_level + (-INT16_MIN))) >> 9);
131 sndlen = *(pData->sound_data_len);
132 bufsize = *(pData->sound_buffer_size);
133 sndpos = *(pData->sound_write_pos);
134 if(*pData->sound_exit) {
138 sndpos = sndpos * format_len;
139 sndlen = sndlen * format_len; // ToDo: Multiple format
140 bufsize = bufsize * format_len; // ToDo: Multiple format
142 if(sndlen >= len) sndlen = len;
143 if((sndpos + sndlen) >= bufsize) { // Need to wrap
144 int len2 = bufsize - sndpos;
145 uint8_t* p = (uint8_t *)(*pData->sound_buf_ptr);
146 uint8_t* s = &stream[spos];
148 #if defined(USE_SDL2)
149 SDL_MixAudioFormat(s, p, pData->sound_format, len2, *(pData->snd_total_volume));
151 SDL_MixAudio(s, p, len2, *(pData->snd_total_volume));
154 len2 = sndlen - len2;
156 *(pData->sound_write_pos) = 0;
158 p = (uint8_t *)(*pData->sound_buf_ptr);
160 #if defined(USE_SDL2)
161 SDL_MixAudioFormat(s, p, pData->sound_format, len2, *(pData->snd_total_volume));
163 SDL_MixAudio(s, p, len2, *(pData->snd_total_volume));
165 *(pData->sound_write_pos) = (len2 / format_len);
166 if(*(pData->sound_buffer_size) <= *(pData->sound_write_pos)) {
167 *(pData->sound_write_pos) = 0;
174 } else { // No Need to wrap
176 uint8_t* p = (uint8_t *)(*pData->sound_buf_ptr);
177 uint8_t* s = &stream[spos];
179 #if defined(USE_SDL2)
180 SDL_MixAudioFormat(s, p, pData->sound_format, len2, *(pData->snd_total_volume));
182 SDL_MixAudio(s, p, len2, *(pData->snd_total_volume));
184 *(pData->sound_write_pos) += (len2 / format_len);
185 if(*(pData->sound_buffer_size) <= *(pData->sound_write_pos)) {
186 *(pData->sound_write_pos) = 0;
191 *(pData->sound_data_len) -= (sndlen / format_len);
192 if(*(pData->sound_data_len) <= 0) return;
193 if(spos >= len3) return;
194 // WIP: Do place wait (1ms)?
199 const _TCHAR *OSD_BASE::get_sound_device_name(int num)
201 if(num < 0) return NULL;
202 if(num >= sound_device_list.count()) return NULL;
203 QString sdev = sound_device_list.at(num);
205 static QByteArray _n;
207 _n = sdev.toUtf8().constData();
209 return (const _TCHAR*)(_n.constData());
212 void OSD_BASE::init_sound_device_list()
214 sound_device_list.clear();
215 #if defined(USE_SDL2)
216 const _TCHAR* drvname = SDL_GetCurrentAudioDriver();
217 if(drvname == nullptr) return;
218 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Using Sound Driver: %s\n", drvname);
219 for(int i = 0; i < SDL_GetNumAudioDevices(0); i++) {
220 QString tmps = QString::fromUtf8(SDL_GetAudioDeviceName(i, 0));
221 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
222 "Audio Device #%d: %s", i, tmps.toLocal8Bit().constData());
223 sound_device_list.append(tmps);
228 void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* presented_samples)
233 bool pre_initialized = sound_initialized;
234 if(sound_initialized) {
238 sound_capture_device_list.clear();
240 for(int ch = 0 ; ch < MAX_CAPTURE_SOUND; ch++) {
242 // ToDo: Close physical device.
243 if(!pre_initialized) {
244 sound_capturing_emu[ch] = false;
246 sound_capture_desc[ch].physical_dev = 0;
247 sound_capture_desc[ch].read_format = AUDIO_S16SYS;
248 sound_capture_desc[ch].read_rate = 0;
249 sound_capture_desc[ch].read_channels = 0;
250 sound_capture_desc[ch].read_samples = 0;
251 sound_capture_desc[ch].read_silence = 0;
252 sound_capture_desc[ch].read_size = 0;
253 sound_capture_desc[ch].read_userdata = NULL;
254 sound_capture_desc[ch].sample_type = 0; // ToDo : ENUM
255 sound_capture_desc[ch].rate = 0;
256 sound_capture_desc[ch].channels = 0;
257 sound_capture_desc[ch].samples = 0;
258 sound_capture_desc[ch].write_size = 0;
259 sound_capture_desc[ch].write_pos = 0;
260 sound_capture_desc[ch].read_data_len = 0;
261 sound_capture_desc[ch].read_buffer_len = 0;
262 sound_capture_desc[ch].read_buffer_ptr = NULL;
263 sound_capture_desc[ch].out_buffer = NULL;
266 for(int num = 0 ; num < MAX_SOUND_CAPTURE_DEVICES; num++) {
267 sound_capture_dev_desc[num].format = AUDIO_S16SYS;
268 sound_capture_dev_desc[num].sample_rate = 0;
269 sound_capture_dev_desc[num].channels = 0;
270 sound_capture_dev_desc[num].buffer_samples = 0;
271 sound_capture_dev_desc[num].silence = 0;
272 sound_capture_dev_desc[num].size = 0;
273 sound_capture_dev_desc[num].callback = audio_capture_callback;
274 sound_capture_dev_desc[num].userdata.format = AUDIO_S16SYS;
275 sound_capture_dev_desc[num].userdata.buffer_size = 0;
276 sound_capture_dev_desc[num].userdata.readlen = 0;
277 sound_capture_dev_desc[num].userdata.writelen = 0;
278 sound_capture_dev_desc[num].userdata.readpos = 0;
279 sound_capture_dev_desc[num].userdata.read_buffer_ptr = NULL;
280 capturing_sound[num] = false;
285 sound_samples = samples;
286 rec_sound_buffer_ptr = 0;
287 sound_ok = sound_started = now_mute = now_record_sound = false;
290 sound_buffer_size = 0;
294 //sound_debug = true;
295 sound_buf_ptr = NULL;
296 sound_initialized = false;
297 // initialize direct sound
299 snd_total_volume = 127;
301 snddata.sound_buf_ptr = (uint8_t**)(&sound_buf_ptr);
302 snddata.sound_buffer_size = &sound_buffer_size;
303 snddata.sound_write_pos = &sound_write_pos;
304 snddata.sound_data_len = &sound_data_len;
305 snddata.snd_total_volume = &snd_total_volume;
306 snddata.sound_exit = &sound_exit;
307 snddata.sound_debug = &sound_debug;
308 snddata.p_config = p_config;
310 snd_spec_req.format = AUDIO_S16SYS;
311 snd_spec_req.channels = 2;
312 snd_spec_req.freq = sound_rate;
313 //snd_spec_req.samples = ((sound_rate * 100) / 1000);
314 snd_spec_req.samples = samples;
315 snd_spec_req.callback = &(this->audio_callback);
316 snd_spec_req.userdata = (void *)&snddata;
317 #if defined(USE_SDL2)
319 if(!(sound_device_list.isEmpty())) {
321 if(p_config->sound_device_num >= sound_device_list.count()) {
322 p_config->sound_device_num = sound_device_list.count() - 1;
324 if(p_config->sound_device_num <= 0) {
325 p_config->sound_device_num = 0;
327 sdev = sound_device_list.at(p_config->sound_device_num);
328 audio_dev_id = SDL_OpenAudioDevice(sdev.toUtf8().constData(), 0,
329 &snd_spec_req, &snd_spec_presented,
331 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Try to open DEVICE #%d: %s -> %s: DEVID=%d\n",
332 p_config->sound_device_num, sdev.toUtf8().constData(), (audio_dev_id <= 0) ? "FAIL" : "SUCCESS", audio_dev_id);
334 audio_dev_id = SDL_OpenAudioDevice("", 0,
335 &snd_spec_req, &snd_spec_presented,
337 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Try to open DEVICE #%d: %s: DEVID=%d\n",
338 p_config->sound_device_num, (audio_dev_id <= 0) ? "FAIL" : "SUCCESS", audio_dev_id);
343 SDL_OpenAudio(&snd_spec_req, &snd_spec_presented);
346 #if defined(USE_SDL2)
347 if(audio_dev_id <= 0) {
348 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,"Failed to initialize sound\n");
349 if(presented_rate != NULL) {
350 *presented_rate = sound_rate;
352 if(presented_samples != NULL) {
353 *presented_samples = sound_samples;
355 sound_initialized = false;
356 sound_ok = sound_first_half = false;
360 snddata.sound_format = snd_spec_presented.format;
361 if((snd_spec_presented.freq != sound_rate) ||
362 (snd_spec_presented.samples != sound_samples)) { // DEINI
363 sound_rate = snd_spec_presented.freq;
364 sound_samples = snd_spec_presented.samples;
366 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,"Sample rate=%d samples=%d\n", sound_rate, sound_samples);
367 if(presented_rate != NULL) {
368 *presented_rate = sound_rate;
370 if(presented_samples != NULL) {
371 *presented_samples = sound_samples;
375 switch(snddata.sound_format) {
380 format_len = sizeof(int16_t);
384 format_len = sizeof(int32_t);
388 format_len = sizeof(float);
391 sound_buffer_size = sound_samples * snd_spec_presented.channels * 2;
392 sound_buf_ptr = (uint8_t *)malloc(sound_buffer_size * format_len);
393 if(sound_buf_ptr == NULL) {
394 #if defined(USE_SDL2)
395 SDL_CloseAudioDevice(audio_dev_id);
402 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
403 "Sound OK: BufSize = %d", sound_buffer_size);
404 memset(sound_buf_ptr, 0x00, sound_buffer_size * format_len);
405 sound_initialized = true;
406 sound_ok = sound_first_half = true;
409 void OSD_BASE::release_sound()
413 sound_initialized = false;
415 for(int num = 0; num < MAX_SOUND_CAPTURE_DEVICES; num++) {
416 if(capturing_sound[num]) {
417 close_sound_capture_device(num, true);
421 for(int ch = 0; ch < MAX_CAPTURE_SOUNDS; ch++) {
422 if(sound_capturing_emu[ch]) {
423 close_capture_sound_emu(ch);
427 #if defined(USE_SDL2)
428 //SDL_PauseAudioDevice(audio_dev_id, 1);
429 SDL_CloseAudioDevice(audio_dev_id);
434 if(sound_buf_ptr != NULL) free(sound_buf_ptr);
435 sound_buf_ptr = NULL;
438 /* END SDL DRIVER: Temporally disabled */
441 /* Note: Below are new sound driver. */
442 #include "./sound-drivers/qt_multimedia/osd_sound_mod_qtmultimedia.h"
443 void OSD_BASE::update_sound(int* extra_frames)
448 if(sound_initialized) {
450 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>sound_drv = m_sound_driver;
451 __UNLIKELY_IF(sound_drv.get() == nullptr) {
456 __UNLIKELY_IF(!(sound_drv->is_driver_started())) {
458 __LIKELY_IF(!(sound_ok)) {
460 __UNLIKELY_IF(p_config != nullptr) {
461 sound_drv->set_volume((int)(p_config->general_sound_level));
468 // Check enough to render accumlated
469 // source (= by VM) rendering data.
470 int64_t sound_samples = sound_drv->get_sample_count();
471 __UNLIKELY_IF(sound_samples <= 0) {
474 int _channels = sound_drv->get_channels();
475 size_t word_size = sound_drv->get_word_size();
476 int64_t _left = sound_drv->get_bytes_left();
477 // Pass 1: Check available to write.
478 __UNLIKELY_IF((_channels <= 0) || (word_size == 0)) {
481 if(_left < (sound_samples * (int64_t)(word_size * _channels))) {
484 // Pass 2: Check elapsed time.
485 int64_t latency_us = sound_drv->get_latency_ms() * 1000;
486 int64_t elapsed_usec = sound_drv->driver_elapsed_usec() % (latency_us * 2);
487 //int64_t processed_usec = sound_drv->driver_processed_usec() % (latency_us * 2);
488 switch(m_sound_period) {
490 if(elapsed_usec > latency_us) {
495 if(elapsed_usec < latency_us) {
500 int16_t* sound_buffer = (int16_t*)create_sound(extra_frames);
501 if(sound_buffer == nullptr) {
504 if(now_record_sound || now_record_video) {
505 if(sound_samples > rec_sound_buffer_ptr) {
506 int samples = sound_samples - rec_sound_buffer_ptr;
507 int length = samples * sizeof(int16_t) * 2; // stereo
508 rec_sound_bytes += length;
509 if(now_record_video) {
510 //AGAR_DebugLog(AGAR_LOG_DEBUG, "Push Sound %d bytes\n", length);
511 emit sig_enqueue_audio((int16_t *)(&(sound_buffer[rec_sound_buffer_ptr * 2])), length);
514 if(now_record_sound) {
515 rec_sound_fio->Fwrite(sound_buffer + rec_sound_buffer_ptr * 2, length, 1);
517 //if(now_record_video) {
518 // // sync video recording
519 // static double frames = 0;
520 // static int prev_samples = -1;
521 // static double prev_fps = -1;
522 // double fps = this->vm_frame_rate();
523 // frames = fps * (double)samples / (double)sound_rate;
525 //printf("Wrote %d samples ptr=%d\n", samples, rec_sound_buffer_ptr);
526 rec_sound_buffer_ptr += samples;
527 if(rec_sound_buffer_ptr >= sound_samples) rec_sound_buffer_ptr = 0;
530 // ToDo: Convert sound format.
531 if(sound_drv.get() != nullptr) {
533 _result = sound_drv->update_sound((void*)sound_buffer, sound_samples);
535 m_sound_period = (m_sound_period + 1) % 2;
536 //printf("%d %ld\n", m_sound_period, _result);
542 void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* presented_samples)
544 // If sound driver hasn't initialized, initialize.
545 if(m_sound_driver.get() == nullptr) {
546 m_sound_driver.reset(
547 new SOUND_MODULE::OUTPUT::M_QT_MULTIMEDIA(this,
550 (samples * 1000) / rate,
554 init_sound_device_list();
555 emit sig_update_sound_output_list();
556 if(p_config != nullptr) {
557 m_sound_driver->set_volume((int)(p_config->general_sound_level));
560 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>sound_drv = m_sound_driver;
562 debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_SOUND,
563 "OSD::%s rate=%d samples=%d m_sound_driver=%llx", __func__, rate, samples, (uintptr_t)(sound_drv.get()));
564 if(sound_drv.get() != nullptr) {
565 sound_drv->initialize_sound(rate, samples, presented_rate, presented_samples);
566 //sound_drv->update_render_point_usec();
568 sound_initialized = true;
572 void OSD_BASE::release_sound()
575 // release Qt Multimedia sound
577 sound_initialized = false;
580 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>sound_drv = m_sound_driver;
581 if(sound_drv.get() != nullptr) {
582 //sound_drv->update_render_point_usec();
583 sound_drv->release_sound();
589 void OSD_BASE::do_update_master_volume(int level)
591 emit sig_set_sound_volume(level);
594 void OSD_BASE::do_set_host_sound_output_device(QString device_name)
596 if(device_name.isEmpty()) return;
597 emit sig_set_sound_device(device_name);
600 const _TCHAR *OSD_BASE::get_sound_device_name(int num)
602 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>sound_drv = m_sound_driver;
603 if(sound_drv.get() != nullptr) {
604 return sound_drv->get_sound_device_name(num);
606 return (const _TCHAR *)nullptr;
609 void OSD_BASE::init_sound_device_list()
611 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>sound_drv = m_sound_driver;
612 sound_device_list.clear();
613 if(sound_drv.get() != nullptr) {
614 std::list<std::string> _l = sound_drv->get_sound_devices_list();
616 for(auto s = _l.begin(); s != _l.end(); ++s) {
617 sound_device_list.append(QString::fromStdString(*s));
618 debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_SOUND,
619 "SOUND DEVICE#%03d %s", _xi, (*s).c_str());
624 void OSD_BASE::mute_sound()
626 if(!now_mute && sound_ok) {
627 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>sound_drv = m_sound_driver;
628 if(sound_drv.get() != nullptr) {
629 sound_drv->mute_sound();
634 void OSD_BASE::stop_sound()
636 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>sound_drv = m_sound_driver;
637 if(sound_drv.get() != nullptr) {
638 if(sound_ok && sound_drv->is_driver_started()) {
639 sound_drv->stop_sound();
643 //sound_initialized = false;
647 int OSD_BASE::get_sound_rate()
649 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>sound_drv = m_sound_driver;
650 if(sound_drv.get() != nullptr) {
651 return sound_drv->get_sample_rate();
657 /* SDL DRIVER: Temporally disabled */
659 void OSD_BASE::convert_sound_format(uint8_t* dst1, uint8_t* dst2, int16_t* src1, int16_t* src2, int samples1, int samples2)
661 if(dst1 == NULL) return;
662 if(snddata.sound_format == AUDIO_S16SYS) { // Not Convert
663 if((src1 != NULL) && (samples1 > 0)) {
664 my_memcpy(dst1, src1, samples1 * sizeof(int16_t));
666 if((src2 != NULL) && (samples2 > 0) && (dst2 != NULL)) {
667 my_memcpy(dst2, src2, samples2 * sizeof(int16_t));
673 #if defined(__LITTLE_ENDIAN__)
674 uint8_t l, h, h1, h2;
676 uint8_t h2, h1, h, l;
682 switch(snddata.sound_format) {
686 int16_t *q = (int16_t*)src1;
687 int8_t* p = (int8_t*)dst1;
689 for(int i = 0; i < samples1; i++) {
695 if((src2 != NULL) && (dst2 != NULL)) {
696 int16_t *q = (int16_t*)src2;
697 int8_t* p = (int8_t*)dst2;
699 for(int i = 0; i < samples2; i++) {
708 int16_t *q = (int16_t*)src1;
709 uint8_t* p = (uint8_t*)dst1;
711 for(int i = 0; i < samples1; i++) {
718 if((src2 != NULL) && (dst2 != NULL)) {
719 int16_t *q = (int16_t*)src2;
720 uint8_t* p = (uint8_t*)dst2;
722 for(int i = 0; i < samples2; i++) {
732 int16_t *q = (int16_t*)src1;
733 int16_t* p = (int16_t*)dst1;
735 for(int i = 0; i < samples1; i++) {
737 #if defined(__LITTLE_ENDIAN__)
740 p[i] = dat.get_2bytes_le_to();
744 if((src2 != NULL) && (dst2 != NULL)) {
745 int16_t* q = (int16_t*)src2;
746 int16_t* p = (int16_t*)dst2;
748 for(int i = 0; i < samples2; i++) {
750 #if defined(__LITTLE_ENDIAN__)
753 p[i] = dat.get_2bytes_le_to();
760 int16_t* q = (int16_t*)src1;
761 uint16_t* p = (uint16_t*)dst1;
764 for(int i = 0; i < samples1; i++) {
767 #if defined(__LITTLE_ENDIAN__)
771 p[i] = dat.get_2bytes_le_to();
775 if((src2 != NULL) && (dst2 != NULL)) {
776 int16_t* q = (int16_t*)src2;
777 uint16_t* p = (uint16_t*)dst2;
780 for(int i = 0; i < samples2; i++) {
783 #if defined(__LITTLE_ENDIAN__)
787 p[i] = dat.get_2bytes_le_to();
794 int16_t *q = (int16_t*)src1;
795 int16_t* p = (int16_t*)dst1;
797 for(int i = 0; i < samples1; i++) {
799 #if defined(__LITTLE_ENDIAN__)
800 p[i] = dat.get_2bytes_be_to();
806 if((src2 != NULL) && (dst2 != NULL)) {
807 int16_t* q = (int16_t*)src2;
808 int16_t* p = (int16_t*)dst2;
810 for(int i = 0; i < samples2; i++) {
812 #if defined(__LITTLE_ENDIAN__)
813 p[i] = dat.get_2bytes_be_to();
822 int16_t* q = (int16_t*)src1;
823 uint16_t* p = (uint16_t*)dst1;
826 for(int i = 0; i < samples1; i++) {
829 #if defined(__LITTLE_ENDIAN__)
831 p[i] = dat.get_2bytes_be_to();
837 if((src2 != NULL) && (dst2 != NULL)) {
838 int16_t* q = (int16_t*)src2;
839 uint16_t* p = (uint16_t*)dst2;
842 for(int i = 0; i < samples2; i++) {
845 #if defined(__LITTLE_ENDIAN__)
847 p[i] = dat.get_2bytes_be_to();
857 uint32_t* p = (uint32_t*)dst1;
858 int32_t* q = (int32_t*)src1;
859 for(int i = 0; i < samples1; i++) {
862 p[i] = EndianToLittle_DWORD(data);
865 if((src2 != NULL) && (dst2 != NULL)) {
867 uint32_t* p = (uint32_t*)dst2;
868 int32_t* q = (int32_t*)src2;
869 for(int i = 0; i < samples2; i++) {
872 p[i] = EndianToLittle_DWORD(data);
879 uint32_t* p = (uint32_t*)dst1;
880 int32_t* q = (int32_t*)src1;
881 for(int i = 0; i < samples1; i++) {
884 p[i] = EndianToBig_DWORD(data);
887 if((src2 != NULL) && (dst2 != NULL)) {
888 uint32_t* p = (uint32_t*)dst2;
889 int32_t* q = (int32_t*)src2;
891 for(int i = 0; i < samples2; i++) {
894 p[i] = EndianToBig_DWORD(data);
900 uint32_t* p = (uint32_t*)dst1;
901 int32_t* q = (int32_t*)src1;
902 for(int i = 0; i < samples1; i++) {
904 float_data.f /= 65536;
905 p[i] = EndianToLittle_DWORD(float_data.d);
908 if((src2 != NULL) && (dst2 != NULL)) {
909 uint32_t* p = (uint32_t*)dst2;
910 int32_t* q = (int32_t*)src2;
911 for(int i = 0; i < samples2; i++) {
913 float_data.f /= 65536;
914 p[i] = EndianToLittle_DWORD(float_data.d);
920 uint32_t* p = (uint32_t*)dst1;
921 int32_t* q = (int32_t*)src1;
922 for(int i = 0; i < samples1; i++) {
924 float_data.f /= 65536;
925 p[i] = EndianToBig_DWORD(float_data.d);
928 if((src2 != NULL) && (dst2 != NULL)) {
929 uint32_t* p = (uint32_t*)dst2;
930 int32_t* q = (int32_t*)src2;
931 for(int i = 0; i < samples2; i++) {
933 float_data.f /= 65536;
934 p[i] = EndianToBig_DWORD(float_data.d);
941 void OSD_BASE::update_sound(int* extra_frames)
947 uint32_t play_c, size1, size2;
949 uint8_t *ptr1, *ptr2;
952 // check current position
953 play_c = sound_write_pos;
954 if(sound_debug) debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_SOUND,
955 "Called time=%d sound_write_pos=%d\n", osd_timer.elapsed(), play_c);
956 if(!sound_first_half) {
957 if((int)play_c < (sound_buffer_size / 2)) {
962 if((int)play_c >= (sound_buffer_size / 2)) {
965 //offset = sound_buffer_size / 2;
968 // sound buffer must be updated
969 Sint16* sound_buffer = (Sint16 *)this->create_sound(extra_frames);
970 if(now_record_sound || now_record_video) {
971 if(sound_samples > rec_sound_buffer_ptr) {
972 int samples = sound_samples - rec_sound_buffer_ptr;
973 int length = samples * sizeof(int16_t) * 2; // stereo
974 rec_sound_bytes += length;
975 if(now_record_video) {
976 //AGAR_DebugLog(AGAR_LOG_DEBUG, "Push Sound %d bytes\n", length);
977 emit sig_enqueue_audio((int16_t *)(&(sound_buffer[rec_sound_buffer_ptr * 2])), length);
980 if(now_record_sound) {
981 rec_sound_fio->Fwrite(sound_buffer + rec_sound_buffer_ptr * 2, length, 1);
983 //if(now_record_video) {
984 // // sync video recording
985 // static double frames = 0;
986 // static int prev_samples = -1;
987 // static double prev_fps = -1;
988 // double fps = this->vm_frame_rate();
989 // frames = fps * (double)samples / (double)sound_rate;
991 //printf("Wrote %d samples ptr=%d\n", samples, rec_sound_buffer_ptr);
992 rec_sound_buffer_ptr += samples;
993 if(rec_sound_buffer_ptr >= sound_samples) rec_sound_buffer_ptr = 0;
1001 if(sound_initialized) {
1002 switch(snddata.sound_format) {
1007 format_len = sizeof(int16_t);
1011 format_len = sizeof(int32_t);
1015 format_len = sizeof(float);
1018 ssize = sound_samples * snd_spec_presented.channels;
1019 pos = sound_data_pos;
1021 ptr1 = (uint8_t*)(&sound_buf_ptr[pos * format_len]);
1022 if(pos2 >= sound_buffer_size) {
1023 size1 = sound_buffer_size - pos;
1024 size2 = pos2 - sound_buffer_size;
1025 ptr2 = &sound_buf_ptr[0];
1031 #if defined(USE_SDL2)
1032 SDL_LockAudioDevice(audio_dev_id);
1038 my_memcpy(ptr1, sound_buffer, size1 * format_len);
1040 if((ptr2) && (size2 > 0)) {
1041 my_memcpy(ptr2, &sound_buffer[size1], size2 * format_len);
1044 convert_sound_format(ptr1, ptr2, sound_buffer, &sound_buffer[size1], size1, size2);
1047 sound_data_len = sound_data_len + ssize;
1048 if(sound_data_len >= sound_buffer_size) sound_data_len = sound_buffer_size;
1049 sound_data_pos = sound_data_pos + ssize;
1050 if(sound_data_pos >= sound_buffer_size) sound_data_pos = sound_data_pos - sound_buffer_size;
1051 if(!sound_started) sound_started = true;
1052 #if defined(USE_SDL2)
1053 SDL_UnlockAudioDevice(audio_dev_id);
1057 //SDL_UnlockAudio();
1058 SDL_PauseAudioDevice(audio_dev_id, 0);
1062 // SDL_PauseAudioDevice(audio_dev_id, 0);
1063 sound_first_half = !sound_first_half;
1067 void OSD_BASE::mute_sound()
1069 if(!now_mute && sound_ok) {
1070 // check current position
1071 uint32_t size1, size2;
1073 uint8_t *ptr1, *ptr2;
1078 #if defined(USE_SDL2)
1079 SDL_LockAudioDevice(audio_dev_id);
1084 switch(snddata.sound_format) {
1089 format_len = sizeof(int16_t);
1093 format_len = sizeof(int32_t);
1097 format_len = sizeof(float);
1100 ssize = sound_buffer_size / 2;
1101 pos = sound_data_pos;
1103 ptr1 = &sound_buf_ptr[pos * format_len];
1104 if(pos2 >= sound_buffer_size) {
1105 size1 = sound_buffer_size - pos;
1106 size2 = pos2 - sound_buffer_size;
1107 ptr2 = &sound_buf_ptr[0];
1115 memset(ptr1, 0x00, size1 * format_len);
1117 if((ptr2) && (size2 > 0)){
1118 memset(ptr2, 0x00, size2 * format_len);
1120 sound_data_pos = (sound_data_pos + ssize) % sound_buffer_size;
1121 #if defined(USE_SDL2)
1122 SDL_UnlockAudioDevice(audio_dev_id);
1130 void OSD_BASE::stop_sound()
1132 if(sound_ok && sound_started) {
1133 //sound_exit = true;
1134 #if defined(USE_SDL2)
1135 SDL_PauseAudioDevice(audio_dev_id, 1);
1139 sound_started = false;
1140 //sound_exit = false;
1144 int OSD_BASE::get_sound_rate()
1146 return snd_spec_presented.freq;
1150 /* END SDL DRIVER: Temporally disabled */
1153 void OSD_BASE::start_record_sound()
1156 if(!now_record_sound) {
1158 QDateTime nowTime = QDateTime::currentDateTime();
1159 QString tmps = QString::fromUtf8("Sound_Save_emu");
1160 tmps = tmps + get_vm_config_name();
1161 tmps = tmps + QString::fromUtf8("_");
1162 tmps = tmps + nowTime.toString(QString::fromUtf8("yyyy-MM-dd_hh-mm-ss.zzz"));
1163 tmps = tmps + QString::fromUtf8(".wav");
1164 strncpy((char *)sound_file_name, tmps.toLocal8Bit().constData(), sizeof(sound_file_name) - 1);
1166 rec_sound_fio = new FILEIO();
1167 if(rec_sound_fio->Fopen(bios_path(sound_file_name), FILEIO_WRITE_BINARY)) {
1168 // write dummy wave header
1169 write_dummy_wav_header((void *)rec_sound_fio);
1171 rec_sound_bytes = 0;
1172 rec_sound_buffer_ptr = 0;
1173 now_record_sound = true;
1175 // failed to open the wave file
1176 delete rec_sound_fio;
1182 void OSD_BASE::stop_record_sound()
1184 #if 0 /* Temporally Disable Caoptuing Sound 20220921 K.O */
1185 if(now_record_sound) {
1187 if(rec_sound_bytes == 0) {
1188 rec_sound_fio->Fclose();
1189 rec_sound_fio->RemoveFile(sound_file_name);
1191 // update wave header
1192 wav_header_t wav_header;
1193 wav_chunk_t wav_chunk;
1195 if(!set_wav_header(&wav_header, &wav_chunk, 2, snd_spec_presented.freq, 16,
1196 (size_t)(rec_sound_bytes + sizeof(wav_header) + sizeof(wav_chunk)))) {
1198 if(!set_wav_header(&wav_header, &wav_chunk, 2, (uint32_t)(m_audioOutputFormat.sampleRate()), 16,
1199 (size_t)(rec_sound_bytes + sizeof(wav_header) + sizeof(wav_chunk)))) {
1201 delete rec_sound_fio;
1202 now_record_sound = false;
1205 rec_sound_fio->Fseek(0, FILEIO_SEEK_SET);
1206 rec_sound_fio->Fwrite(&wav_header, sizeof(wav_header_t), 1);
1207 rec_sound_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
1208 rec_sound_fio->Fclose();
1210 delete rec_sound_fio;
1211 now_record_sound = false;
1214 #endif /* Temporally Disable Caoptuing Sound 20220921 K.O */
1218 void OSD_BASE::restart_record_sound()
1220 bool tmp = now_record_sound;
1221 stop_record_sound();
1223 start_record_sound();
1227 #if 0 /* Temporally Disable Caoptuing Sound 20220921 K.O */
1228 int OSD_BASE::get_sound_rate()
1230 std::shared_ptr<SOUND_MODULE::OUTPUT::M_BASE>out_driver = m_output_driver;
1231 if(out_driver.get() != nullptr) {
1232 return out_driver->get_sample_rate();
1236 #endif /* Temporally Disable Caoptuing Sound 20220921 K.O */
1239 void OSD_BASE::close_capture_sound_emu(int ch)
1242 if(ch >= MAX_CAPTURE_SOUNDS) return;
1243 if(sound_capture_desc[ch].out_buffer != NULL) {
1244 free(sound_capture_desc[ch].out_buffer);
1246 sound_capture_desc[ch].out_buffer = NULL;
1247 sound_capturing_emu[ch] = false;
1250 void *OSD_BASE::get_capture_sound_buffer(int ch)
1252 if(ch < 0) return NULL;
1253 if(ch >= MAX_CAPTURE_SOUNDS) return NULL;
1254 return sound_capture_desc[ch].out_buffer;
1257 bool OSD_BASE::is_capture_sound_buffer(int ch)
1259 if(ch < 0) return false;
1260 if(ch >= MAX_CAPTURE_SOUNDS) return false;
1261 if(sound_capture_desc[ch].out_buffer == NULL) return false;
1262 return sound_capturing_emu[ch];
1264 void *OSD_BASE::open_capture_sound_emu(int ch, int rate, int channels, int sample_type, int samples, int physical_device_num)
1266 if(ch < 0) return nullptr;
1267 if(ch >= MAX_CAPTURE_SOUNDS) return nullptr;
1271 close_capture_sound_emu(ch);
1272 sound_capture_desc[ch].rate = rate;
1273 sound_capture_desc[ch].channels = channels;
1274 sound_capture_desc[ch].samples = samples;
1275 sound_capture_desc[ch].sample_type = sample_type;
1276 sound_capture_desc[ch].physical_dev = physical_device_num;
1278 if((physical_device_num >= 0) && (physical_device_num < sound_capture_device_list.count()) && (physical_device_num < MAX_SOUND_CAPTURE_DEVICES)) {
1279 if(!(capturing_sound[physical_device_num])) {
1280 stat = open_sound_capture_device(physical_device_num, (rate < 44100) ? 44100 : rate, (channels > 2) ? channels : 2);
1286 switch(sample_type) {
1287 case SAMPLE_TYPE_UINT8:
1288 case SAMPLE_TYPE_SINT8:
1289 p = malloc(sizeof(uint8_t) * channels * (samples + 100));
1291 case SAMPLE_TYPE_UINT16_BE:
1292 case SAMPLE_TYPE_SINT16_BE:
1293 case SAMPLE_TYPE_UINT16_LE:
1294 case SAMPLE_TYPE_SINT16_LE:
1295 p = malloc(sizeof(uint16_t) * channels * (samples + 100));
1297 case SAMPLE_TYPE_UINT32_BE:
1298 case SAMPLE_TYPE_SINT32_BE:
1299 case SAMPLE_TYPE_UINT32_LE:
1300 case SAMPLE_TYPE_SINT32_LE:
1301 p = malloc(sizeof(uint32_t) * channels * (samples + 100));
1303 case SAMPLE_TYPE_FLOAT_BE:
1304 case SAMPLE_TYPE_FLOAT_LE:
1305 p = malloc(sizeof(float) * channels * (samples + 100));
1309 sound_capture_desc[ch].out_buffer = (uint8_t *)p;
1310 sound_capturing_emu[ch] = true;
1315 bool OSD_BASE::open_sound_capture_device(int num, int req_rate, int req_channels)
1317 if(num < 0) return false;
1318 if(num >= MAX_SOUND_CAPTURE_DEVICES) return false;
1319 if(sound_capture_device_list.count() <= num) return false;
1322 SDL_AudioSpec desired;
1323 req.freq = req_rate;
1324 req.channels = req_channels;
1326 req.format = AUDIO_S16SYS;
1327 req.samples = (sizeof(sound_capture_buffer[num]) / sizeof(int16_t)) / req_channels;
1328 req.callback = &(this->audio_capture_callback);
1329 req.userdata = (void *)(&(sound_capture_dev_desc[num].userdata));
1331 if(!(capturing_sound[num])) {
1332 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);
1333 if(sound_capture_desc[num].physical_dev <= 0) {
1334 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());
1335 sound_capture_desc[num].physical_dev = -1;
1339 capturing_sound[num] = true;
1340 sound_capture_dev_desc[num].format = desired.format;
1341 sound_capture_dev_desc[num].sample_rate = desired.freq;
1342 sound_capture_dev_desc[num].channels = desired.channels;
1343 sound_capture_dev_desc[num].buffer_samples = desired.samples;
1344 sound_capture_dev_desc[num].size = desired.size;
1345 sound_capture_dev_desc[num].callback = desired.callback;
1346 sound_capture_dev_desc[num].silence = desired.silence;
1347 int buflen = desired.samples * desired.channels;
1348 switch(desired.format) {
1351 buflen = buflen * sizeof(int8_t);
1357 buflen = buflen * sizeof(int16_t);
1361 buflen = buflen * sizeof(int32_t);
1365 buflen = buflen * sizeof(float);
1371 sound_capture_dev_desc[num].userdata.buffer_size = buflen;
1372 sound_capture_dev_desc[num].userdata.format = desired.format;
1373 sound_capture_dev_desc[num].userdata.readlen = 0;
1374 sound_capture_dev_desc[num].userdata.writelen = 0;
1375 sound_capture_dev_desc[num].userdata.readpos = 0;
1376 sound_capture_dev_desc[num].userdata.writepos = 0;
1377 sound_capture_dev_desc[num].userdata.read_buffer_ptr = &(sound_capture_buffer[num][0]);
1378 memset(&(sound_capture_buffer[num][0]), 0x00, buflen);
1380 for(int ch = 0; ch < MAX_SOUND_CAPTURE_DEVICES; ch++) {
1381 if(sound_capture_desc[ch].physical_dev == num) {
1382 sound_capture_desc[ch].read_format = desired.format;
1383 sound_capture_desc[ch].read_rate = desired.freq;
1384 sound_capture_desc[ch].read_silence = desired.silence;
1385 sound_capture_desc[ch].read_size = desired.size;
1386 sound_capture_desc[ch].read_channels = desired.channels;
1387 sound_capture_desc[ch].read_samples = desired.samples;
1388 sound_capture_desc[ch].read_callback = desired.callback;
1389 sound_capture_desc[ch].read_userdata = desired.userdata;
1391 sound_capture_desc[ch].read_pos = 0;
1392 sound_capture_desc[ch].read_data_len = 0;
1393 sound_capture_desc[ch].read_buffer_len = buflen;
1394 sound_capture_desc[ch].read_buffer_ptr = (uint8_t *)(&(sound_capture_buffer[num][0]));
1404 bool OSD_BASE::close_sound_capture_device(int num, bool force)
1406 // ToDo: Check capturing entries
1408 if((capturing_sound[num]) && (sound_capture_desc[num].physical_dev > 0)) {
1409 SDL_CloseAudioDevice(sound_capture_desc[num].physical_dev);