2 Skelton for retropc emulator
4 Author : K.Ohta <whatisthis.sowhat _at_ gmail.com>
11 #include "../fileio.h"
16 //#include "csp_logger.h"
17 #include "gui/menu_flags.h"
23 void OSD_BASE::audio_callback(void *udata, Uint8 *stream, int len)
32 sdl_snddata_t *pData = (sdl_snddata_t *)udata;
33 if(pData == NULL) return;
37 memset(stream, 0x00, len);
39 if(pData->p_config->general_sound_level < -32768) pData->p_config->general_sound_level = -32768;
40 if(pData->p_config->general_sound_level > 32767) pData->p_config->general_sound_level = 32767;
41 *pData->snd_total_volume = (uint8_t)(((uint32_t)(pData->p_config->general_sound_level + 32768)) >> 9);
42 sndlen = *pData->sound_data_len;
43 if(*(pData->sound_buffer_size) <= *(pData->sound_write_pos)) { // Wrap
44 *(pData->sound_write_pos) = 0;
46 len2 = *(pData->sound_buffer_size) - *(pData->sound_write_pos);
47 if(*pData->sound_exit) {
50 if(len2 >= sndlen) len2 = sndlen; // Okay
51 if((spos + len2) >= (int)(len / sizeof(Sint16))) {
52 len2 = (len / sizeof(Sint16)) - spos;
54 if((*(pData->sound_write_pos) + len2) >= *(pData->sound_buffer_size) ) len2 = *(pData->sound_buffer_size) - *(pData->sound_write_pos);
56 //if(*(pData->sound_debug)) debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_SOUND,
57 // "Callback,sound_write_pos=%d,spos=%d,len=%d,len2=%d",
58 // *(pData->sound_write_pos), spos, len, len2);
59 if((len2 > 0) && (sndlen > 0)){
60 writepos = *pData->sound_write_pos;
61 p = (Uint8 *)(*pData->sound_buf_ptr);
63 s = &stream[spos * 2];
64 SDL_MixAudio(s, (Uint8 *)p, len2 * 2, *(pData->snd_total_volume));
65 *(pData->sound_data_len) -= len2;
66 if(*(pData->sound_data_len) <= 0) *(pData->sound_data_len) = 0;
67 *pData->sound_write_pos += len2;
70 if(spos >= (len / 2)) return;
71 if(*(pData->sound_data_len) <= 0) return;
72 //while(*(pData->sound_data_len) <= 0) {
73 // QThread::usleep(500);
74 // if(*pData->sound_exit) return;
78 if(*pData->sound_exit) return;
82 void OSD_BASE::initialize_sound(int rate, int samples)
88 sound_samples = samples;
89 rec_sound_buffer_ptr = 0;
90 sound_ok = sound_started = now_mute = now_record_sound = false;
93 sound_buffer_size = 0;
99 sound_initialized = false;
100 // initialize direct sound
102 snd_total_volume = 127;
104 snddata.sound_buf_ptr = &sound_buf_ptr;
105 snddata.sound_buffer_size = &sound_buffer_size;
106 snddata.sound_write_pos = &sound_write_pos;
107 snddata.sound_data_len = &sound_data_len;
108 snddata.snd_total_volume = &snd_total_volume;
109 snddata.sound_exit = &sound_exit;
110 snddata.sound_debug = &sound_debug;
111 snddata.p_config = p_config;
113 snd_spec_req.format = AUDIO_S16SYS;
114 snd_spec_req.channels = 2;
115 snd_spec_req.freq = sound_rate;
116 //snd_spec_req.samples = ((sound_rate * 100) / 1000);
117 snd_spec_req.samples = samples;
118 snd_spec_req.callback = &(this->audio_callback);
119 snd_spec_req.userdata = (void *)&snddata;
120 #if defined(USE_SDL2)
121 for(i = 0; i < SDL_GetNumAudioDevices(0); i++) {
122 //devname = SDL_GetAudioDeviceName(i, 0);
123 QString tmps = QString::fromUtf8(SDL_GetAudioDeviceName(i, 0));
124 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
125 "Audio Device: %s", tmps.toLocal8Bit().constData());
128 SDL_OpenAudio(&snd_spec_req, &snd_spec_presented);
132 sound_buffer_size = sound_samples * snd_spec_presented.channels * 2;
133 sound_buf_ptr = (Sint16 *)malloc(sound_buffer_size * sizeof(Sint16));
134 if(sound_buf_ptr == NULL) {
135 #if defined(USE_SDL2)
136 SDL_CloseAudioDevice(audio_dev_id);
143 debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND,
144 "Sound OK: BufSize = %d", sound_buffer_size);
145 memset(sound_buf_ptr, 0x00, sound_buffer_size * sizeof(Sint16));
146 //#if defined(USE_SDL2)
147 // SDL_PauseAudioDevice(audio_dev_id, 0);
149 // SDL_PauseAudio(0);
151 sound_initialized = true;
152 sound_ok = sound_first_half = true;
155 void OSD_BASE::release_sound()
159 sound_initialized = false;
161 #if defined(USE_SDL2)
162 //SDL_PauseAudioDevice(audio_dev_id, 1);
163 SDL_CloseAudioDevice(audio_dev_id);
168 if(sound_buf_ptr != NULL) free(sound_buf_ptr);
169 sound_buf_ptr = NULL;
174 void OSD_BASE::update_sound(int* extra_frames)
180 uint32_t play_c, size1, size2;
185 // check current position
186 play_c = sound_write_pos;
187 if(sound_debug) debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_SOUND,
188 "Called time=%d sound_write_pos=%d\n", osd_timer.elapsed(), play_c);
189 if(!sound_first_half) {
190 if((int)play_c < (sound_buffer_size / 2)) {
195 if((int)play_c >= (sound_buffer_size / 2)) {
198 //offset = sound_buffer_size / 2;
201 // sound buffer must be updated
202 Sint16* sound_buffer = (Sint16 *)this->create_sound(extra_frames);
203 if(now_record_sound || now_record_video) {
204 if(sound_samples > rec_sound_buffer_ptr) {
205 int samples = sound_samples - rec_sound_buffer_ptr;
206 int length = samples * sizeof(int16_t) * 2; // stereo
207 rec_sound_bytes += length;
208 if(now_record_video) {
209 //AGAR_DebugLog(AGAR_LOG_DEBUG, "Push Sound %d bytes\n", length);
210 emit sig_enqueue_audio((int16_t *)(&(sound_buffer[rec_sound_buffer_ptr * 2])), length);
213 if(now_record_sound) {
214 rec_sound_fio->Fwrite(sound_buffer + rec_sound_buffer_ptr * 2, length, 1);
216 //if(now_record_video) {
217 // // sync video recording
218 // static double frames = 0;
219 // static int prev_samples = -1;
220 // static double prev_fps = -1;
221 // double fps = this->vm_frame_rate();
222 // frames = fps * (double)samples / (double)sound_rate;
224 //printf("Wrote %d samples ptr=%d\n", samples, rec_sound_buffer_ptr);
225 rec_sound_buffer_ptr += samples;
226 if(rec_sound_buffer_ptr >= sound_samples) rec_sound_buffer_ptr = 0;
233 if(sound_initialized) {
234 ssize = sound_samples * snd_spec_presented.channels;
236 pos = sound_data_pos;
238 ptr1 = &sound_buf_ptr[pos];
239 if(pos2 >= sound_buffer_size) {
240 size1 = sound_buffer_size - pos;
241 size2 = pos2 - sound_buffer_size;
242 ptr2 = &sound_buf_ptr[0];
248 #if defined(USE_SDL2)
249 SDL_LockAudioDevice(audio_dev_id);
254 my_memcpy(ptr1, sound_buffer, size1 * sizeof(Sint16));
257 my_memcpy(ptr2, &sound_buffer[size1], size2 * sizeof(Sint16));
259 sound_data_len = sound_data_len + ssize;
260 if(sound_data_len >= sound_buffer_size) sound_data_len = sound_buffer_size;
261 sound_data_pos = sound_data_pos + ssize;
262 if(sound_data_pos >= sound_buffer_size) sound_data_pos = sound_data_pos - sound_buffer_size;
263 if(!sound_started) sound_started = true;
264 #if defined(USE_SDL2)
265 SDL_UnlockAudioDevice(audio_dev_id);
270 SDL_PauseAudioDevice(audio_dev_id, 0);
274 // SDL_PauseAudioDevice(audio_dev_id, 0);
275 sound_first_half = !sound_first_half;
279 void OSD_BASE::mute_sound()
281 if(!now_mute && sound_ok) {
282 // check current position
283 uint32_t size1, size2;
290 #if defined(USE_SDL2)
291 SDL_LockAudioDevice(audio_dev_id);
295 ssize = sound_buffer_size / 2;
296 pos = sound_data_pos;
298 ptr1 = &sound_buf_ptr[pos];
299 if(pos2 >= sound_buffer_size) {
300 size1 = sound_buffer_size - pos;
301 size2 = pos2 - sound_buffer_size;
302 ptr2 = &sound_buf_ptr[0];
310 memset(ptr1, 0x00, size1 * sizeof(Sint16));
313 memset(ptr2, 0x00, size2 * sizeof(Sint16));
315 sound_data_pos = (sound_data_pos + ssize) % sound_buffer_size;
316 #if defined(USE_SDL2)
317 SDL_UnlockAudioDevice(audio_dev_id);
325 void OSD_BASE::stop_sound()
327 if(sound_ok && sound_started) {
329 #if defined(USE_SDL2)
330 SDL_PauseAudioDevice(audio_dev_id, 1);
334 sound_started = false;
335 //sound_exit = false;
339 void OSD_BASE::start_record_sound()
342 if(!now_record_sound) {
344 QDateTime nowTime = QDateTime::currentDateTime();
345 QString tmps = QString::fromUtf8("Sound_Save_emu");
346 tmps = tmps + get_vm_config_name();
347 tmps = tmps + QString::fromUtf8("_");
348 tmps = tmps + nowTime.toString(QString::fromUtf8("yyyy-MM-dd_hh-mm-ss.zzz"));
349 tmps = tmps + QString::fromUtf8(".wav");
350 strncpy((char *)sound_file_name, tmps.toLocal8Bit().constData(), sizeof(sound_file_name) - 1);
352 rec_sound_fio = new FILEIO();
353 if(rec_sound_fio->Fopen(bios_path(sound_file_name), FILEIO_WRITE_BINARY)) {
354 // write dummy wave header
355 write_dummy_wav_header((void *)rec_sound_fio);
358 rec_sound_buffer_ptr = 0;
359 now_record_sound = true;
361 // failed to open the wave file
362 delete rec_sound_fio;
368 void OSD_BASE::stop_record_sound()
370 if(now_record_sound) {
372 if(rec_sound_bytes == 0) {
373 rec_sound_fio->Fclose();
374 rec_sound_fio->RemoveFile(sound_file_name);
376 // update wave header
377 wav_header_t wav_header;
378 wav_chunk_t wav_chunk;
383 memcpy(wav_header.riff_chunk.id, "RIFF", 4);
385 tmpval32.d = rec_sound_bytes + sizeof(wav_header_t) - 8;
386 wav_header.riff_chunk.size = tmpval32.get_4bytes_le_to();
388 memcpy(wav_header.wave, "WAVE", 4);
389 memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
392 wav_header.fmt_chunk.size = tmpval32.get_4bytes_le_to();
395 wav_header.format_id = tmpval16.get_2bytes_le_to();
398 wav_header.channels = tmpval16.get_2bytes_le_to();
401 wav_header.sample_bits = tmpval16.get_2bytes_le_to();
403 tmpval32.d = snd_spec_presented.freq;
404 wav_header.sample_rate = tmpval32.get_4bytes_le_to();
406 tmpval16.w = wav_header.channels * wav_header.sample_bits / 8;
407 wav_header.block_size = tmpval16.get_2bytes_le_to();
409 tmpval32.d = wav_header.sample_rate * wav_header.block_size;
410 wav_header.data_speed = tmpval32.get_4bytes_le_to();
412 memcpy(wav_chunk.id, "data", 4);
414 tmpval32.d = rec_sound_bytes;
415 wav_chunk.size = tmpval32.get_4bytes_le_to();
417 if(!set_wav_header(&wav_header, &wav_chunk, 2, snd_spec_presented.freq, 16,
418 (size_t)(rec_sound_bytes + sizeof(wav_header) + sizeof(wav_chunk)))) {
419 delete rec_sound_fio;
420 now_record_sound = false;
424 rec_sound_fio->Fseek(0, FILEIO_SEEK_SET);
425 rec_sound_fio->Fwrite(&wav_header, sizeof(wav_header_t), 1);
426 rec_sound_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
427 rec_sound_fio->Fclose();
429 delete rec_sound_fio;
430 now_record_sound = false;
435 void OSD_BASE::restart_record_sound()
437 bool tmp = now_record_sound;
440 start_record_sound();
444 int OSD_BASE::get_sound_rate()
446 return snd_spec_presented.freq;
449 void OSD_BASE::load_sound_file(int id, const _TCHAR *name, int16_t **data, int *dst_size)
451 if(data != NULL) *data = NULL;
452 if(dst_size != NULL) *dst_size = 0;
455 void OSD_BASE::free_sound_file(int id, int16_t **data)
459 void OSD_BASE::init_sound_files()
463 void OSD_BASE::release_sound_files()