[Qt][OSD][Sound] SDL_MixAudioFormat() *MUST* use for SDL2, shouldm't use SDL_MixAudio for SDL2.
[Qt][UI] Select sound output devices.
#endif
config.sound_latency = 1; // 100msec
config.sound_strict_rendering = true;
+ config.sound_device_num = 0; // Add 20190221
#ifdef USE_FLOPPY_DISK
config.sound_noise_fdd = true;
#endif
// sound
config.sound_frequency = MyGetPrivateProfileInt(_T("Sound"), _T("Frequency"), config.sound_frequency, config_path);
config.sound_latency = MyGetPrivateProfileInt(_T("Sound"), _T("Latency"), config.sound_latency, config_path);
- config.sound_strict_rendering = MyGetPrivateProfileBool(_T("Sound"), _T("StrictRendering"), config.sound_strict_rendering, config_path);
+ config.sound_strict_rendering = MyGetPrivateProfileInt(_T("Sound"), _T("StrictRendering"), config.sound_strict_rendering, config_path);
+ config.sound_device_num = MyGetPrivateProfileBool(_T("Sound"), _T("DeviceNumber"), config.sound_device_num, config_path);
#ifdef USE_FLOPPY_DISK
config.sound_noise_fdd = MyGetPrivateProfileBool(_T("Sound"), _T("NoiseFDD"), config.sound_noise_fdd, config_path);;
#endif
MyWritePrivateProfileInt(_T("Sound"), _T("Frequency"), config.sound_frequency, config_path);
MyWritePrivateProfileInt(_T("Sound"), _T("Latency"), config.sound_latency, config_path);
MyWritePrivateProfileBool(_T("Sound"), _T("StrictRendering"), config.sound_strict_rendering, config_path);
+ MyWritePrivateProfileInt(_T("Sound"), _T("DeviceNumber"), config.sound_device_num, config_path);
#ifdef USE_FLOPPY_DISK
MyWritePrivateProfileBool(_T("Sound"), _T("NoiseFDD"), config.sound_noise_fdd, config_path);
#endif
int sound_frequency;
int sound_latency;
bool sound_strict_rendering;
+ int sound_device_num;
+
#if defined(_USE_QT)
int general_sound_level;
#endif
osd->main_window_handle = hwnd;
osd->instance_handle = hinst;
#endif
- osd->initialize(sound_rate, sound_samples);
+ int presented_rate, presented_samples;
+ osd->initialize(sound_rate, sound_samples, &presented_rate, &presented_samples);
+ sound_rate = presented_rate;
+ sound_samples = presented_samples;
// initialize vm
vm = new VM(this);
osd->vm = vm;
#if defined(_USE_QT)
osd->reset_vm_node();
#endif
+ int presented_rate;
+ int presented_samples;
sound_rate = sound_frequency_table[config.sound_frequency];
sound_samples = (int)(sound_rate * sound_latency_table[config.sound_latency] + 0.5);
+ osd->initialize_sound(sound_rate, sound_samples, &presented_rate, &presented_samples);
+ if((sound_rate != presented_rate) ||
+ (sound_samples != presented_samples)) {
+ sound_rate = presented_rate;
+ sound_samples = presented_samples;
+ }
vm->initialize_sound(sound_rate, sound_samples);
#ifdef USE_SOUND_VOLUME
for(int i = 0; i < USE_SOUND_VOLUME; i++) {
message("* qt/osd")
-SET(THIS_LIB_VERSION 2.18.0)
+SET(THIS_LIB_VERSION 2.18.2)
set(s_qt_osd_headers
osd_base.h
if(p_emu == NULL) return NULL;
return (_TCHAR *)p_emu->get_osd()->get_vm_node_name(id);
}
+
+const _TCHAR *USING_FLAGS_EXT::get_sound_device_name(int num)
+{
+ if(p_emu == NULL) return NULL;
+ return (const _TCHAR *)(p_emu->get_osd()->get_sound_device_name(num));
+}
+
+int USING_FLAGS_EXT::get_sound_device_num()
+{
+ if(p_emu == NULL) return -1;
+ return p_emu->get_osd()->get_sound_device_num();
+}
+
int get_vm_node_size();
void set_vm_node_name(int id, const _TCHAR *name);
_TCHAR *get_vm_node_name(int id);
+ const _TCHAR *get_sound_device_name(int num);
+ int get_sound_device_num();
};
}
csp_logger->set_osd(emu->get_osd());
csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL, "InitInstance() OK.");
-
+ // ToDo: Update raltime.
+ for(int i = 0; i < 16; i++) {
+ const _TCHAR* sp = emu->get_osd()->get_sound_device_name(i);
+ QString sname;
+ sname.clear();
+ if(sp != NULL) {
+ sname = QString::fromUtf8(sp);
+ }
+ rMainWindow->do_set_host_sound_name(i, sname);
+ }
QObject::connect(GuiMain, SIGNAL(lastWindowClosed()),
rMainWindow, SLOT(on_actionExit_triggered()));
message("* qt/emuutils")
-SET(THIS_LIB_VERSION 2.15.2)
+SET(THIS_LIB_VERSION 2.15.3)
set(s_qt_emuutils_headers
../gui/csp_logger.h
message("* qt/gui")
-set(THIS_LIB_VERSION 2.18.2)
+set(THIS_LIB_VERSION 2.18.3)
#include(cotire)
#include(PrecompiledHeader)
void setWriteProtect(bool b) {write_protect = b;}
public slots:
+ void on_set_host_sound_device(void);
void set_boot_mode(void);
void set_cpu_type(void);
void set_cpupower(void);
int sig_freq(int);
int sig_latency(int);
int sig_sounddevice(int);
+ int sig_set_host_sound_device(int);
int sig_set_dipsw(int, bool);
int sig_screen_aspect(int);
int sig_screen_size(int, int);
//tx->setFormat(QOpenGLTexture::RGBA8_UNorm);
if(main_texture_buffer != 0) {
- main_mutex->lock();
+ //main_mutex->lock();
this->unmap_vram_texture();
map_base_address = NULL;
extfunc->glDeleteBuffers(1, &main_texture_buffer);
main_texture_buffer = 0;
- main_mutex->unlock();
+ //main_mutex->unlock();
}
{
- main_mutex->lock();
+ //main_mutex->lock();
extfunc->glGenBuffers(1, &main_texture_buffer);
extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, main_texture_buffer);
//extfunc->glBufferData(GL_PIXEL_UNPACK_BUFFER, w * h * sizeof(uint32_t), ip->constBits(), GL_DYNAMIC_COPY);
map_vram_texture();
pixel_width = w;
pixel_height = h;
- main_mutex->unlock();
+ //main_mutex->unlock();
}
extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} else {
- main_mutex->lock();
+ //main_mutex->lock();
extfunc->glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, pixel_width *pixel_height * sizeof(scrntype_t));
extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
extfunc->glDeleteSync(sync_fence);
extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
extfunc->glDeleteSync(sync_fence);
sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- main_mutex->unlock();
+ //main_mutex->unlock();
}
#else
uVramTextureID->setData(*p, QOpenGLTexture::DontGenerateMipMaps);
if(map_base_address == NULL) {
return NULL;
} else {
- main_mutex->lock();
+ //main_mutex->lock();
//extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
scrntype_t *p = (scrntype_t *)map_base_address;
p = p + (pixel_width * y);
//printf("%08x\n", (uintptr_t)p);
- main_mutex->unlock();
+ //main_mutex->unlock();
return p;
}
}
// Sound
QActionGroup *actionGroup_Sound_Freq;
QActionGroup *actionGroup_Sound_Latency;
+ QActionGroup *actionGroup_Sound_HostDevices;
//class Action_Control *actionSoundCMT;
class Action_Control *action_VolumeDialog;
class Action_Control *actionSoundPlayTape;
class Action_Control *actionSoundStrictRendering;
class Action_Control *action_SoundFilesFDD;
class Action_Control *action_SoundFilesRelay;
+ class Action_Control *action_HostSoundDevice[16];
//QMenu *menuLogToConsole;
//QMenu *menuLogToSyslog;
QMenu *menuDevLogToConsole;
QMenu *menuSound;
QMenu *menuOutput_Frequency;
QMenu *menuSound_Latency;
+ QMenu *menuSound_HostDevices;
QMenu *menuMachine;
QMenu *menuRecord;
QMenu *menuRecord_sound;
void set_sound_device(int);
void do_set_sound_strict_rendering(bool f);
void do_set_sound_play_tape(bool f);
-
+ void do_set_host_sound_device(int num);
+ void do_set_host_sound_name(int num, QString sname);
void set_monitor_type(int);
void message_status_bar(QString);
void resize_statusbar(int w, int h);
EMU *get_emu(void);
void set_osd(OSD *p);
OSD *get_osd(void);
+ virtual const _TCHAR *get_sound_device_name(int num);
+ virtual int get_sound_device_num();
virtual int get_vm_node_size();
virtual void set_vm_node_name(int id, const _TCHAR *name);
{
return p_emu;
}
+
+const _TCHAR *USING_FLAGS::get_sound_device_name(int num)
+{
+ return NULL;
+}
+
+int USING_FLAGS::get_sound_device_num()
+{
+ return -1;
+}
emit sig_latency(s_num);
}
+void Object_Menu_Control::on_set_host_sound_device(void) {
+ emit sig_set_host_sound_device(s_num);
+}
+
+void Ui_MainWindowBase::do_set_host_sound_device(int num)
+{
+ if(p_config != NULL) {
+ p_config->sound_device_num = num;
+ }
+}
+
+void Ui_MainWindowBase::do_set_host_sound_name(int num, QString s)
+{
+ if(num < 0) return;
+ if(num >= 16) return;
+
+ if(s.isEmpty()) {
+ if(action_HostSoundDevice[num] != NULL) {
+ action_HostSoundDevice[num]->setVisible(false);
+ }
+ } else {
+ if(action_HostSoundDevice[num] != NULL) {
+ action_HostSoundDevice[num]->setVisible(true);
+ action_HostSoundDevice[num]->setText(s);
+ }
+ }
+}
void Ui_MainWindowBase::do_set_sound_strict_rendering(bool f)
{
//connect(actionSoundStrictRendering, SIGNAL(toggled(bool)),
// this, SLOT(do_set_sound_strict_rendering(bool)));
//menuSound->addAction(actionSoundStrictRendering);
+
+ menuSound_HostDevices = new QMenu(menuSound);
+ menuSound_HostDevices->setObjectName(QString::fromUtf8("menuSound_HostDevices"));
+ menuSound->addAction(menuSound_HostDevices->menuAction());
+ for(i = 0; i < 16; i++) {
+ if(action_HostSoundDevice[i] != NULL) {
+ menuSound_HostDevices->addAction(action_HostSoundDevice[i]);
+ connect(action_HostSoundDevice[i], SIGNAL(triggered()),
+ action_HostSoundDevice[i]->binds, SLOT(on_set_host_sound_device()));
+ connect(action_HostSoundDevice[i]->binds, SIGNAL(sig_set_host_sound_device(int)),
+ this, SLOT(do_set_host_sound_device(int)));
+ }
+ }
+
+ menuSound->addSeparator();
menuOutput_Frequency = new QMenu(menuSound);
menuOutput_Frequency->setObjectName(QString::fromUtf8("menuOutput_Frequency"));
QString tmps;
double dval;
//int freq = 48000;
+
+ actionGroup_Sound_HostDevices = new QActionGroup(this);
+ for(i = 0; i < 16; i++) {
+ action_HostSoundDevice[i] = new Action_Control(this, using_flags);
+ tmps.setNum(i);
+ tmps = QString::fromUtf8("action_HostSoundDevice") + tmps;
+
+ action_HostSoundDevice[i]->setObjectName(tmps);
+ action_HostSoundDevice[i]->setCheckable(true);
+ action_HostSoundDevice[i]->binds->setNumber(i);
+ if(i == p_config->sound_device_num) {
+ action_HostSoundDevice[i]->setChecked(true);
+ //freq = using_flags->get_s_freq_table(i);
+ }
+ actionGroup_Sound_HostDevices->addAction(action_HostSoundDevice[i]);
+ }
+
actionGroup_Sound_Freq = new QActionGroup(this);
actionGroup_Sound_Freq->setExclusive(true);
for(i = 0; i < 8; i++) {
actionSoundPlayTape->setEnabled(false);
}
+ menuSound_HostDevices->setTitle(QApplication::translate("MenuSound", "Output to:", 0));
+ menuSound_HostDevices->setToolTip(QApplication::translate("MenuSound", "Select sound device to output.\nThis effects after re-start this emulator.", 0));
+
menuSound->setTitle(QApplication::translate("MenuSound", "Sound", 0));
menuOutput_Frequency->setTitle(QApplication::translate("MenuSound", "Output Frequency", 0));
menuSound_Latency->setTitle(QApplication::translate("MenuSound", "Sound Latency", 0));
extern std::string cpp_homedir;
extern std::string my_procname;
-void OSD::initialize(int rate, int samples)
+void OSD::initialize(int rate, int samples, int* presented_rate, int* presented_samples)
{
// get module path
QString tmp_path;
initialize_input();
initialize_printer();
initialize_screen();
- initialize_sound(rate, samples);
+ initialize_sound(rate, samples, presented_rate, presented_samples);
#if defined(USE_SOUND_FILES)
init_sound_files();
#endif
public:
OSD(USING_FLAGS *p, CSP_Logger *logger);
~OSD();
- void initialize(int rate, int samples);
+ void initialize(int rate, int samples, int* presented_rate, int* presented_samples);
void release();
void power_off();
parent_thread = parent;
}
-void OSD_BASE::initialize(int rate, int samples)
+void OSD_BASE::initialize(int rate, int samples, int* presented_rate, int* presented_samples)
{
}
#include <QList>
#include <QThread>
#include <QString>
+#include <QStringList>
#include <QImage>
#include <SDL.h>
//#include "simd_types.h"
bool self_invalidate;
// sound
- void initialize_sound(int rate, int samples);
+#if defined(USE_SDL2)
+ SDL_AudioDeviceID audio_dev_id;
+#else
+ int audio_dev_id;
+#endif
+ SDL_AudioSpec snd_spec_req, snd_spec_presented;
void release_sound();
static void audio_callback(void *udata, Uint8 *stream, int len);
int sound_rate, sound_samples;
bool sound_ok, sound_started, now_mute;
bool sound_first_half;
+ QStringList sound_device_list;
_TCHAR sound_file_name[_MAX_PATH];
FILEIO* rec_sound_fio;
bool sound_initialized;
Sint16 *sound_buf_ptr;
Uint8 snd_total_volume;
-#if defined(USE_SDL2)
- SDL_AudioDeviceID audio_dev_id;
-#else
- int audio_dev_id;
-#endif
- SDL_AudioSpec snd_spec_req, snd_spec_presented;
// video device
virtual void initialize_video();
int host_cpus;
bool now_auto_key;
- virtual void initialize(int rate, int samples);
+ virtual void initialize(int rate, int samples, int* presented_rate, int* presented_samples);
+ // sound
+ virtual void initialize_sound(int rate, int samples, int* presented_rate, int* presented_samples);
virtual void release();
virtual void power_off();
void suspend();
void start_record_sound();
void stop_record_sound();
void restart_record_sound();
+
+ const _TCHAR *get_sound_device_name(int num);
+ int get_sound_device_num();
+
bool now_record_sound;
int get_sound_rate();
// Wrapper : Sound
Uint8 *s;
int writepos;
int sndlen;
-
+ //printf("Callback: udata=%08x stream=%08x len=%d\n", udata, stream, len);
sdl_snddata_t *pData = (sdl_snddata_t *)udata;
if(pData == NULL) return;
p = (Uint8 *)(*pData->sound_buf_ptr);
p = &p[writepos * 2];
s = &stream[spos * 2];
+#if defined(USE_SDL2)
+ SDL_MixAudioFormat(s, (Uint8*)p, pData->sound_format, len2 * 2, *(pData->snd_total_volume));
+#else
SDL_MixAudio(s, (Uint8 *)p, len2 * 2, *(pData->snd_total_volume));
+#endif
*(pData->sound_data_len) -= len2;
if(*(pData->sound_data_len) <= 0) *(pData->sound_data_len) = 0;
*pData->sound_write_pos += len2;
} while(spos < len);
}
-void OSD_BASE::initialize_sound(int rate, int samples)
+const _TCHAR *OSD_BASE::get_sound_device_name(int num)
+{
+ if(num < 0) return NULL;
+ if(num >= sound_device_list.count()) return NULL;
+ QString sdev = sound_device_list.value(num);
+ sdev.truncate(64);
+ return (const _TCHAR*)(sdev.toUtf8().constData());
+}
+
+int OSD_BASE::get_sound_device_num()
+{
+ return sound_device_list.count();
+}
+
+void OSD_BASE::initialize_sound(int rate, int samples, int* presented_rate, int* presented_samples)
{
std::string devname;
int i;
+ if(sound_initialized) {
+ release_sound();
+ }
sound_rate = rate;
sound_samples = samples;
rec_sound_buffer_ptr = 0;
snd_spec_req.samples = samples;
snd_spec_req.callback = &(this->audio_callback);
snd_spec_req.userdata = (void *)&snddata;
-#if defined(USE_SDL2)
+#if defined(USE_SDL2)
+ debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Using Sound Driver: %s\n", SDL_GetCurrentAudioDriver());
+ sound_device_list.clear();
for(i = 0; i < SDL_GetNumAudioDevices(0); i++) {
- //devname = SDL_GetAudioDeviceName(i, 0);
QString tmps = QString::fromUtf8(SDL_GetAudioDeviceName(i, 0));
debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
- "Audio Device: %s", tmps.toLocal8Bit().constData());
+ "Audio Device #%d: %s", i, tmps.toLocal8Bit().constData());
+ sound_device_list.append(tmps);
}
#endif
- SDL_OpenAudio(&snd_spec_req, &snd_spec_presented);
+#if defined(USE_SDL2)
+
+ //QString sdev = QString::fromUtf8("\"") + sound_device_list.at(audio_dev_id) + QString::fromUtf8("\"");
+ //audio_dev_id = SDL_OpenAudioDevice(NULL, 0, &snd_spec_req, &snd_spec_presented, SDL_AUDIO_ALLOW_ANY_CHANGE);
+ QString sdev;
+ sdev = sound_device_list.at(p_config->sound_device_num);
+ audio_dev_id = SDL_OpenAudioDevice(sdev.toUtf8().constData(), 0,
+ &snd_spec_req, &snd_spec_presented,
+ 0);
+ debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND, "Try to openDEVICE #%d: %s -> %s: DEVID=%d\n",
+ p_config->sound_device_num, sdev.toUtf8().constData(), (audio_dev_id <= 0) ? "FAIL" : "SUCCESS", audio_dev_id);
+#else
audio_dev_id = 1;
-
+ SDL_OpenAudio(&snd_spec_req, &snd_spec_presented);
+#endif
+
+#if defined(USE_SDL2)
+ if(audio_dev_id <= 0) {
+ debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,"Failed to initialize sound\n");
+ if(presented_rate != NULL) {
+ *presented_rate = sound_rate;
+ }
+ if(presented_samples != NULL) {
+ *presented_samples = sound_samples;
+ }
+ sound_initialized = false;
+ sound_ok = sound_first_half = false;
+ return;
+ }
+#endif
+ snddata.sound_format = snd_spec_presented.format;
+ if((snd_spec_presented.freq != sound_rate) ||
+ (snd_spec_presented.samples != sound_samples)) { // DEINI
+ sound_rate = snd_spec_presented.freq;
+ sound_samples = snd_spec_presented.samples;
+ }
+ debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,"Sample rate=%d samples=%d\n", sound_rate, sound_samples);
+ if(presented_rate != NULL) {
+ *presented_rate = sound_rate;
+ }
+ if(presented_samples != NULL) {
+ *presented_samples = sound_samples;
+ }
// secondary buffer
sound_buffer_size = sound_samples * snd_spec_presented.channels * 2;
sound_buf_ptr = (Sint16 *)malloc(sound_buffer_size * sizeof(Sint16));
debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
"Sound OK: BufSize = %d", sound_buffer_size);
memset(sound_buf_ptr, 0x00, sound_buffer_size * sizeof(Sint16));
-//#if defined(USE_SDL2)
-// SDL_PauseAudioDevice(audio_dev_id, 0);
-//#else
-// SDL_PauseAudio(0);
-//#endif
sound_initialized = true;
sound_ok = sound_first_half = true;
}
//SDL_PauseAudioDevice(audio_dev_id, 1);
SDL_CloseAudioDevice(audio_dev_id);
#else
- //SDL_PauseAudio(1);
SDL_CloseAudio();
#endif
+ stop_record_sound();
if(sound_buf_ptr != NULL) free(sound_buf_ptr);
sound_buf_ptr = NULL;
// stop recording
- stop_record_sound();
}
void OSD_BASE::update_sound(int* extra_frames)
Uint8 *snd_total_volume;
bool *sound_exit;
bool *sound_debug;
+ SDL_AudioFormat sound_format;
config_t *p_config;
} sdl_snddata_t;
return mode + WINDOW_MODE_BASE;
}
+
void OSD::initialize_video()
{
movie_loader = NULL;