2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
14 #define EVENT_SIGNAL 0
17 //#ifndef DATAREC_FAST_FWD_SPEED
18 //#define DATAREC_FAST_FWD_SPEED 10
20 //#ifndef DATAREC_FAST_REW_SPEED
21 //#define DATAREC_FAST_REW_SPEED 10
24 void DATAREC::initialize()
27 __DATAREC_SOUND = osd->check_feature(_T("DATAREC_SOUND"));
28 if(osd->check_feature(_T("DATAREC_PCM_VOLUME"))) {
29 pcm_max_vol = (int)osd->get_feature_int_value(_T("DATAREC_PCM_VOLUME"));
31 __DATAREC_SOUND_LEFT = osd->check_feature(_T("DATAREC_SOUND_LEFT"));
32 __DATAREC_SOUND_RIGHT = osd->check_feature(_T("DATAREC_SOUND_RIGHT"));
34 __DATAREC_FAST_FWD_SPEED = 10.0;
35 if(osd->check_feature(_T("DATAREC_FAST_FWD_SPEED"))) {
36 __DATAREC_FAST_FWD_SPEED = osd->get_feature_double_value(_T("DATAREC_FAST_FWD_SPEED"));
38 __DATAREC_FAST_REW_SPEED = 10.0;
39 if(osd->check_feature(_T("DATAREC_FAST_REW_SPEED"))) {
40 __DATAREC_FAST_REW_SPEED = osd->get_feature_double_value(_T("DATAREC_FAST_REW_SPEED"));
43 if(osd->check_feature(_T("_MZ80B"))) __TYPE_MZ80B = true;
44 if(osd->check_feature(_T("_MZ2000"))) __TYPE_MZ80B = true;
45 if(osd->check_feature(_T("_MZ2200"))) __TYPE_MZ80B = true;
46 play_fio = new FILEIO();
47 rec_fio = new FILEIO();
49 memset(rec_file_path, sizeof(rec_file_path), 1);
50 play = rec = remote = trigger = false;
52 in_signal = out_signal = false;
56 buffer = buffer_bak = NULL;
57 //#ifdef DATAREC_SOUND
61 buffer_ptr = buffer_length = 0;
62 is_wav = is_tap = is_t77 = false;
66 pcm_last_vol_l = pcm_last_vol_r = 0;
67 //#ifdef DATAREC_SOUND
68 sound_last_vol_l = sound_last_vol_r = 0;
72 if(d_noise_play != NULL) {
73 d_noise_play->set_device_name(_T("Noise Player (CMT Play)"));
74 d_noise_play->load_wav_file(_T("RELAY_ON.WAV"));
75 d_noise_play->set_mute(!config.sound_noise_cmt);
77 if(d_noise_stop != NULL) {
78 d_noise_stop->set_device_name(_T("Noise Player (CMT Stop)"));
79 d_noise_stop->load_wav_file(_T("RELAYOFF.WAV"));
80 d_noise_stop->set_mute(!config.sound_noise_cmt);
82 if(d_noise_fast != NULL) {
83 d_noise_fast->set_device_name(_T("Noise Player (CMT Fast)"));
84 d_noise_fast->load_wav_file(_T("FAST_FWD.WAV"));
85 d_noise_fast->set_loop(true);
86 d_noise_fast->set_mute(!config.sound_noise_cmt);
91 register_frame_event(this);
98 pcm_prev_clock = get_current_clock();
99 pcm_positive_clocks = pcm_negative_clocks = 0;
102 void DATAREC::release()
109 void DATAREC::write_signal(int id, uint32_t data, uint32_t mask)
111 bool signal = ((data & mask) != 0);
113 if(id == SIG_DATAREC_MIC) {
114 if(out_signal != signal) {
118 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
120 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
122 pcm_prev_clock = get_current_clock();
126 if(prev_clock != 0) {
128 positive_clocks += get_passed_clock(prev_clock);
130 negative_clocks += get_passed_clock(prev_clock);
132 prev_clock = get_current_clock();
136 } else if(id == SIG_DATAREC_REMOTE) {
139 } else if(id == SIG_DATAREC_TRIG) {
140 // L->H: remote signal is switched
141 if(signal && !trigger) {
149 void DATAREC::event_frame()
154 //#ifdef DATAREC_SOUND
155 if(__DATAREC_SOUND) {
156 if(remote && (play || rec) && ff_rew == 0 && signal_changed > 10 && !config.sound_play_tape && sound_sample == 0) {
157 request_skip_frames();
161 if(remote && (play || rec) && ff_rew == 0 && signal_changed > 10 && !config.sound_play_tape) {
163 request_skip_frames();
169 void DATAREC::event_callback(int event_id, int err)
171 if(event_id == EVENT_SIGNAL) {
174 my_stprintf_s(message, 1024, _T("Fast Forward (%d %%)"), get_tape_position());
175 } else if(ff_rew < 0) {
176 my_stprintf_s(message, 1024, _T("Fast Rewind (%d %%)"), get_tape_position());
178 my_stprintf_s(message, 1024, _T("Play (%d %%)"), get_tape_position());
180 bool signal = in_signal;
182 if(buffer_ptr >= 0 && buffer_ptr < buffer_length) {
184 signal = ((buffer[buffer_ptr] & 0x80) != 0);
188 //#ifdef DATAREC_SOUND
189 if(__DATAREC_SOUND) {
190 if(sound_buffer != NULL && ff_rew == 0) {
191 sound_sample = sound_buffer[buffer_ptr];
199 if((buffer_ptr = max(buffer_ptr - 1, 0)) == 0) {
200 set_remote(false); // top of tape
204 if((buffer_ptr = min(buffer_ptr + 1, buffer_length)) == buffer_length) {
205 set_remote(false); // end of tape
212 if((buffer_bak != NULL) && (buffer != NULL)) {
213 my_memcpy(buffer, buffer_bak, buffer_length);
216 set_remote(false); // top of tape
219 while(buffer_ptr < buffer_length) {
220 if((buffer[buffer_ptr] & 0x7f) == 0) {
221 if(++buffer_ptr == buffer_length) {
222 set_remote(false); // end of tape
226 signal = ((buffer[buffer_ptr] & 0x80) != 0);
228 signal = ((buffer[buffer_ptr] & 0x80) != 0);
229 uint8_t tmp = buffer[buffer_ptr];
230 buffer[buffer_ptr] = (tmp & 0x80) | ((tmp & 0x7f) - 1);
235 set_remote(false); // end of tape
240 // notify the signal is changed
241 if(signal != in_signal) {
243 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
245 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
247 pcm_prev_clock = get_current_clock();
252 write_signals(&outputs_ear, in_signal ? 0xffffffff : 0);
255 if(apss_buffer != NULL) {
256 int ptr = (apss_ptr++) % (sample_rate * 2);
257 if(apss_buffer[ptr]) {
263 apss_buffer[ptr] = in_signal;
265 if(apss_ptr >= sample_rate * 2) {
266 double rate = (double)apss_count / (double)(sample_rate * 2);
267 if(rate > 0.9 || rate < 0.1) {
269 if(apss_remain > 0) {
271 } else if(apss_remain < 0) {
274 write_signals(&outputs_apss, 0xffffffff);
275 apss_signals = false;
279 write_signals(&outputs_apss, 0);
285 } else if(rec && buffer != NULL) {
287 positive_clocks += get_passed_clock(prev_clock);
289 negative_clocks += get_passed_clock(prev_clock);
292 if(positive_clocks != 0 || negative_clocks != 0) {
293 buffer[buffer_ptr] = (255 * positive_clocks) / (positive_clocks + negative_clocks);
295 buffer[buffer_ptr] = 0;
297 if(++buffer_ptr >= buffer_length) {
299 for(int i = 0; i < buffer_length; i += 8) {
301 for(int j = 0, bit = 0x80; j < 8; j++, bit >>= 1) {
302 if(i + j < buffer_length && buffer[i + j] >= 0x80) {
306 rec_fio->FputUint8(val);
309 rec_fio->Fwrite(buffer, buffer_length, 1);
314 bool signal = (positive_clocks > negative_clocks);
315 uint16_t data = (buffer[buffer_ptr] << 8) | buffer[buffer_ptr + 1];
316 if(signal != ((data & 0x8000) != 0)) {
317 if((buffer_ptr += 2) >= buffer_length) {
318 rec_fio->Fwrite(buffer, buffer_length, 1);
321 data = signal ? 0x8001 : 0x0001;
322 } else if((data & 0x7fff) < 0x7fff) {
325 buffer[buffer_ptr + 0] = data >> 8;
326 buffer[buffer_ptr + 1] = data & 0xff;
328 bool prev_signal = ((buffer[buffer_ptr] & 0x80) != 0);
329 bool cur_signal = (positive_clocks > negative_clocks);
330 if(prev_signal != cur_signal || (buffer[buffer_ptr] & 0x7f) == 0x7f) {
331 if(++buffer_ptr >= buffer_length) {
332 rec_fio->Fwrite(buffer, buffer_length, 1);
335 buffer[buffer_ptr] = cur_signal ? 0x80 : 0;
337 buffer[buffer_ptr]++;
339 prev_clock = get_current_clock();
340 positive_clocks = negative_clocks = 0;
345 void DATAREC::set_remote(bool value)
347 if(remote != value) {
349 if(d_noise_play != NULL) {
350 d_noise_play->play();
352 if(d_noise_fast != NULL && ff_rew != 0) {
353 d_noise_fast->play();
356 if(d_noise_stop != NULL) {
357 d_noise_stop->play();
359 if(d_noise_fast != NULL) {
360 d_noise_fast->stop();
368 void DATAREC::set_ff_rew(int value)
370 if(ff_rew != value) {
371 if(register_id != -1) {
372 cancel_event(this, register_id);
376 if(d_noise_fast != NULL && remote) {
377 d_noise_fast->play();
380 if(d_noise_fast != NULL) {
381 d_noise_fast->stop();
385 apss_signals = false;
390 bool DATAREC::do_apss(int value)
397 set_ff_rew(value > 0 ? 1 : -1);
400 while(apss_remain != 0 && remote) {
401 event_callback(EVENT_SIGNAL, 0);
403 result = (apss_remain == 0);
412 my_stprintf_s(message, 1024, _T("APSS Forward (%d %%)"), get_tape_position());
414 my_stprintf_s(message, 1024, _T("APSS Forward"));
418 my_stprintf_s(message, 1024, _T("APSS Rewind (%d %%)"), get_tape_position());
420 my_stprintf_s(message, 1024, _T("APSS Rewind"));
426 void DATAREC::update_event()
428 if(remote && (play || rec)) {
429 if(register_id == -1) {
431 register_event(this, EVENT_SIGNAL, sample_usec / __DATAREC_FAST_FWD_SPEED, true, ®ister_id);
432 } else if(ff_rew < 0) {
433 register_event(this, EVENT_SIGNAL, sample_usec / __DATAREC_FAST_REW_SPEED, true, ®ister_id);
436 my_stprintf_s(message, 1024, _T("Record"));
438 register_event(this, EVENT_SIGNAL, sample_usec, true, ®ister_id);
440 prev_clock = get_current_clock();
441 positive_clocks = negative_clocks = 0;
444 if(register_id != -1) {
445 cancel_event(this, register_id);
448 if(buffer_ptr >= buffer_length) {
449 my_stprintf_s(message, 1024, _T("Stop (End-of-Tape)"));
450 } else if(buffer_ptr <= 0) {
451 my_stprintf_s(message, 1024, _T("Stop (Beginning-of-Tape)"));
453 my_stprintf_s(message, 1024, _T("Stop (%d %%)"), get_tape_position());
456 my_stprintf_s(message, 1024, _T("Stop"));
463 //#ifdef DATAREC_SOUND
464 if(__DATAREC_SOUND) {
465 if(!(play && remote)) {
470 write_signals(&outputs_remote, remote ? 0xffffffff : 0);
471 write_signals(&outputs_rotate, (register_id != -1) ? 0xffffffff : 0);
472 write_signals(&outputs_end, (buffer_ptr == buffer_length) ? 0xffffffff : 0);
473 write_signals(&outputs_top, (buffer_ptr == 0) ? 0xffffffff : 0);
475 update_realtime_render();
478 void DATAREC::update_realtime_render()
480 bool value = (remote && (play || rec) && ff_rew == 0 && config.sound_play_tape);
482 if(realtime != value) {
483 set_realtime_render(this, value);
488 bool DATAREC::play_tape(const _TCHAR* file_path)
492 if(play_fio->Fopen(file_path, FILEIO_READ_BINARY)) {
493 if(check_file_extension(play_fio->FilePath(), _T(".wav")) || check_file_extension(play_fio->FilePath(), _T(".mti"))) {
494 // standard PCM wave file
495 if((buffer_length = load_wav_image(0)) != 0) {
496 play = is_wav = true;
498 } else if(check_file_extension(play_fio->FilePath(), _T(".t77"))) {
499 // FUJITSU FM-7 series tape image
500 if((buffer_length = load_t77_image()) != 0) {
501 buffer = (uint8_t *)malloc(buffer_length);
503 play = is_wav = true;
505 } else if(check_file_extension(play_fio->FilePath(), _T(".tap"))) {
506 // SHARP X1 series tape image
507 if((buffer_length = load_tap_image()) != 0) {
508 buffer = (uint8_t *)malloc(buffer_length);
510 play = is_wav = true;
512 } else if(check_file_extension(play_fio->FilePath(), _T(".mzt")) || check_file_extension(play_fio->FilePath(), _T(".mzf")) || check_file_extension(play_fio->FilePath(), _T(".m12"))) {
513 // SHARP MZ series tape image
514 if((buffer_length = load_mzt_image()) != 0) {
515 buffer = (uint8_t *)malloc(buffer_length);
517 play = is_wav = true;
519 } else if(check_file_extension(play_fio->FilePath(), _T(".mtw"))) {
522 play_fio->Fread(header, sizeof(header), 1);
523 uint16_t size = header[0x12] | (header[0x13] << 8);
524 // load standard PCM wave file
525 if((buffer_length = load_wav_image(sizeof(header) + size)) != 0) {
526 play = is_wav = true;
528 } else if(check_file_extension(play_fio->FilePath(), _T(".p6"))) {
529 // NEC PC-6001/6601 series tape image
530 if((buffer_length = load_p6_image(false)) != 0) {
531 buffer = (uint8_t *)malloc(buffer_length);
532 load_p6_image(false);
533 play = is_wav = true;
535 } else if(check_file_extension(play_fio->FilePath(), _T(".p6t"))) {
536 // NEC PC-6001/6601 series tape image
537 if((buffer_length = load_p6_image(true)) != 0) {
538 buffer = (uint8_t *)malloc(buffer_length);
540 play = is_wav = true;
542 } else if(check_file_extension(play_fio->FilePath(), _T(".bin"))) {
543 // HITACH BASIC Master Jr tape image (bm2)
544 if((buffer_length = load_bmjr_image()) != 0) {
545 buffer = (uint8_t *)malloc(buffer_length);
547 play = is_wav = true;
549 } else if(check_file_extension(play_fio->FilePath(), _T(".cas"))) {
550 // standard cas image for my emulator
551 if((buffer_length = load_cas_image()) != 0) {
552 buffer = (uint8_t *)malloc(buffer_length);
554 play = is_wav = true;
560 if(!is_wav && buffer_length != 0) {
561 buffer_bak = (uint8_t *)malloc(buffer_length);
562 my_memcpy(buffer_bak, buffer, buffer_length);
565 // get the first signal
566 bool signal = ((buffer[0] & 0x80) != 0);
567 if(signal != in_signal) {
569 write_signals(&outputs_ear, signal ? 0xffffffff : 0);
574 apss_buffer_length = sample_rate * 2;
575 apss_buffer = (bool *)calloc(apss_buffer_length, 1);
576 apss_ptr = apss_count = 0;
577 apss_signals = false;
578 write_signals(&outputs_apss, 0);
585 bool DATAREC::rec_tape(const _TCHAR* file_path)
589 if(rec_fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
590 my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
592 sample_usec = 1000000. / sample_rate;
593 buffer_length = 1024 * 1024;
594 buffer = (uint8_t *)calloc(buffer_length, 1);
596 if(check_file_extension(file_path, _T(".wav"))) {
598 uint8_t dummy[sizeof(wav_header_t) + sizeof(wav_chunk_t)];
599 memset(dummy, 0, sizeof(dummy));
600 rec_fio->Fwrite(dummy, sizeof(dummy), 1);
602 } else if(check_file_extension(file_path, _T(".tap"))) {
604 rec_fio->FputUint32((uint32_t)sample_rate);
605 is_wav = is_tap = true;
606 } else if(check_file_extension(file_path, _T(".t77"))) {
609 sample_rate = (int)(1000000.0 / sample_usec + 0.5);
611 rec_fio->Fwrite((void *)("XM7 TAPE IMAGE 0"), 16, 1);
612 rec_fio->FputUint16(0); // marker
615 buffer[0] = out_signal ? 0x80 : 0;
619 buffer[0] = out_signal ? 0x80 : 0;
627 void DATAREC::close_tape()
632 play = rec = is_wav = is_tap = is_t77 = false;
633 buffer_ptr = buffer_length = 0;
639 write_signals(&outputs_ear, 0);
643 void DATAREC::close_file()
645 if(play_fio->IsOpened()) {
648 if(rec_fio->IsOpened()) {
651 for(int i = 0; i < buffer_ptr; i += 8) {
653 for(int j = 0, bit = 0x80; j < 8; j++, bit >>= 1) {
654 if(i + j < buffer_ptr && buffer[i + j] >= 0x80) {
658 rec_fio->FputUint8(val);
661 rec_fio->Fwrite(buffer, buffer_ptr + 2, 1);
665 rec_fio->Fwrite(buffer, buffer_ptr + 1, 1);
674 if(buffer_bak != NULL) {
678 //#ifdef DATAREC_SOUND
679 if(__DATAREC_SOUND) {
680 if(sound_buffer != NULL) {
686 if(apss_buffer != NULL) {
692 // standard PCM wave file
694 void adjust_zero_position(int16_t *wav_buffer, int samples, int sample_rate)
696 int16_t *zero_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
697 int width = (int)((double)sample_rate / 1000.0 + 0.5);
699 for(int i = width; i < samples - width; i++) {
700 int max_sample = -65536, min_sample = 65536;
701 for(int j = -width; j < width; j++) {
702 if(max_sample < (int)wav_buffer[i + j]) max_sample = (int)wav_buffer[i + j];
703 if(min_sample > (int)wav_buffer[i + j]) min_sample = (int)wav_buffer[i + j];
705 if(max_sample - min_sample > 4096) {
706 zero_buffer[i] = (int16_t)((max_sample + min_sample) / 2);
708 zero_buffer[i] = wav_buffer[i];
711 for(int i = 0; i < samples; i++) {
712 wav_buffer[i] -= zero_buffer[(i < width) ? width : (i < samples - width) ? i : (samples - width - 1)];
716 int DATAREC::load_wav_image(int offset)
722 play_fio->Fseek(offset, FILEIO_SEEK_SET);
723 play_fio->Fread(&header, sizeof(header), 1);
724 if(header.format_id != 1 || !(header.sample_bits == 8 || header.sample_bits == 16)) {
727 play_fio->Fseek(header.fmt_chunk.size - 16, FILEIO_SEEK_CUR);
729 play_fio->Fread(&chunk, sizeof(chunk), 1);
730 if(strncmp(chunk.id, "data", 4) == 0) {
733 play_fio->Fseek(chunk.size, FILEIO_SEEK_CUR);
736 int samples = chunk.size / header.channels, loaded_samples = 0;
737 if(header.sample_bits == 16) {
740 sample_rate = header.sample_rate;
741 sample_usec = 1000000. / sample_rate;
745 #define TMP_LENGTH (0x10000 * header.channels)
747 uint8_t *tmp_buffer = (uint8_t *)malloc(TMP_LENGTH);
748 play_fio->Fread(tmp_buffer, TMP_LENGTH, 1);
750 #define GET_SAMPLE { \
751 for(int ch = 0; ch < header.channels; ch++) { \
752 if(header.sample_bits == 16) { \
759 pair.b.l = tmp_buffer[tmp_ptr++]; \
760 pair.b.h = tmp_buffer[tmp_ptr++]; \
761 sample[ch] = pair.s16; \
763 sample[ch] = (tmp_buffer[tmp_ptr++] - 128) * 256; \
766 if(tmp_ptr == TMP_LENGTH) { \
767 play_fio->Fread(tmp_buffer, TMP_LENGTH, 1); \
773 if(__DATAREC_SOUND) {
774 if(!config.wave_shaper[drive_num] || header.channels > 1) {
778 if(!config.wave_shaper[drive_num]) {
782 //#ifdef DATAREC_SOUND
783 // if(!config.wave_shaper[drive_num] || header.channels > 1) {
785 // if(!config.wave_shaper[drive_num]) {
789 //#ifdef DATAREC_SOUND
790 if(__DATAREC_SOUND) {
791 if(header.channels > 1) {
792 sound_buffer_length = samples * sizeof(int16_t);
793 sound_buffer = (int16_t *)malloc(sound_buffer_length);
797 int16_t *wav_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
798 for(int i = 0, tmp_ptr = 0; i < samples; i++) {
801 int16_t sample_signal = sample[0];
802 //#ifdef DATAREC_SOUND
803 if(__DATAREC_SOUND) {
804 if(header.channels > 1) {
805 //#ifdef DATAREC_SOUND_LEFT
806 if(__DATAREC_SOUND_LEFT) {
807 sample_signal = sample[1];
808 sound_buffer[i] = sample[0];
811 sound_buffer[i] = sample[1];
817 wav_buffer[i] = sample_signal;
819 adjust_zero_position(wav_buffer, samples, header.sample_rate);
821 // copy to dest buffer
822 buffer = (uint8_t *)malloc(samples);
823 bool prev_signal = false;
825 int16_t max_sample = 0, min_sample = 0;
827 for(int i = 0 /*, tmp_ptr = 0 */; i < samples; i++) {
828 int16_t sample_signal = wav_buffer[i];
829 bool signal = (sample_signal > 0);
831 if(!prev_signal && signal) {
832 if(!(min_sample < -2048)) {
833 for(int j = top_index; j < i; j++) {
837 } else if(prev_signal && !signal) {
838 if(!(max_sample > 2048)) {
839 for(int j = top_index; j < i; j++) {
844 if(prev_signal != signal) {
846 max_sample = min_sample = 0;
849 if(max_sample < sample_signal) {
850 max_sample = sample_signal;
853 if(min_sample > sample_signal) {
854 min_sample = sample_signal;
857 buffer[i] = (signal ? 0xff : 0);
858 prev_signal = signal;
861 if(!(min_sample < -2048)) {
862 for(int j = top_index; j < samples; j++) {
867 if(!(max_sample > 2048)) {
868 for(int j = top_index; j < samples; j++) {
875 loaded_samples = samples;
878 int16_t *wav_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
879 for(int i = 0, tmp_ptr = 0; i < samples; i++) {
882 wav_buffer[i] = sample[0];
884 adjust_zero_position(wav_buffer, samples, header.sample_rate);
886 // t=0 : get thresholds
887 // t=1 : get number of samples
888 // t=2 : load samples
889 #define FREQ_SCALE 16
890 int min_threshold = (int)(header.sample_rate * FREQ_SCALE / 2400.0 / 2.0 / 3.0 + 0.5);
891 int max_threshold = (int)(header.sample_rate * FREQ_SCALE / 1200.0 / 2.0 * 3.0 + 0.5);
892 int half_threshold, hi_count, lo_count;
893 int *counts = (int *)calloc(max_threshold, sizeof(int));
895 for(int t = 0; t < 3; t++) {
896 int count_positive = 0, count_negative = 0;
897 bool prev_signal = false;
899 for(int i = 0; i < samples - 1; i++) {
900 int prev = wav_buffer[i], next = wav_buffer[i + 1];
901 double diff = (double)(next - prev) / FREQ_SCALE;
902 for(int j = 0; j < FREQ_SCALE; j++) {
903 int sample = prev + (int)(diff * j + 0.5);
904 bool signal = (sample > 0);
906 if(!prev_signal && signal) {
908 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
909 counts[count_positive]++;
912 int count_p = count_positive / FREQ_SCALE;
913 int count_n = count_negative / FREQ_SCALE;
914 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
915 count_p = (count_positive > half_threshold) ? hi_count : lo_count;
916 if(count_negative < max_threshold) {
921 for(int j = 0; j < count_p; j++) buffer[loaded_samples++] = 0xff;
922 for(int j = 0; j < count_n; j++) buffer[loaded_samples++] = 0x00;
924 loaded_samples += count_p + count_n;
927 count_positive = count_negative = 0;
934 prev_signal = signal;
938 long sum_value = 0, sum_count = 0, half_tmp;
939 for(int i = 0; i < max_threshold; i++) {
940 sum_value += i * counts[i];
941 sum_count += counts[i];
943 // 1920 = 2400 * 0.6 + 1200 * 0.4
944 if(sum_count > 60 * 1920) {
945 half_tmp = (int)((double)sum_value / (double)sum_count + 0.5);
947 half_tmp = (int)(header.sample_rate * FREQ_SCALE / 1920.0 / 2.0 + 0.5);
950 sum_value = sum_count = 0;
951 for(int i = 0; i < half_tmp; i++) {
952 sum_value += i * counts[i];
953 sum_count += counts[i];
955 double lo_tmp = (double)sum_value / (double)sum_count;
957 sum_value = sum_count = 0;
958 for(int i = half_tmp; i < half_tmp * 2; i++) {
959 sum_value += i * counts[i];
960 sum_count += counts[i];
962 double hi_tmp = (double)sum_value / (double)sum_count;
964 half_threshold = (int)((lo_tmp + hi_tmp) / 2 + 0.5);
965 min_threshold = (int)(2 * lo_tmp - half_threshold + 0.5);
966 max_threshold = (int)(2 * hi_tmp - half_threshold + 0.5);
967 lo_count = (int)(lo_tmp / FREQ_SCALE + 0.5);
968 hi_count = (int)(hi_tmp / FREQ_SCALE + 0.5);
970 int count_p = count_positive / FREQ_SCALE;
971 int count_n = count_negative / FREQ_SCALE;
972 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
973 count_p = (count_positive > half_threshold) ? hi_count : lo_count;
974 if(count_negative < max_threshold) {
979 for(int j = 0; j < count_p; j++) buffer[loaded_samples++] = 0xff;
980 for(int j = 0; j < count_n; j++) buffer[loaded_samples++] = 0x00;
982 loaded_samples += count_p + count_n;
986 buffer = (uint8_t *)malloc(loaded_samples);
987 //#ifdef DATAREC_SOUND
988 if(__DATAREC_SOUND) {
989 if(header.channels > 1) {
990 sound_buffer_length = loaded_samples * sizeof(int16_t);
991 sound_buffer = (int16_t *)malloc(sound_buffer_length);
1003 return loaded_samples;
1007 void DATAREC::save_wav_image()
1009 // write samples remained in buffer
1010 if(buffer_ptr > 0) {
1011 rec_fio->Fwrite(buffer, buffer_ptr, 1);
1013 uint32_t length = rec_fio->Ftell();
1015 wav_header_t wav_header;
1016 wav_chunk_t wav_chunk;
1018 memcpy(wav_header.riff_chunk.id, "RIFF", 4);
1019 wav_header.riff_chunk.size = length - 8;
1020 memcpy(wav_header.wave, "WAVE", 4);
1021 memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
1022 wav_header.fmt_chunk.size = 16;
1023 wav_header.format_id = 1;
1024 wav_header.channels = 1;
1025 wav_header.sample_rate = sample_rate;
1026 wav_header.data_speed = sample_rate;
1027 wav_header.block_size = 1;
1028 wav_header.sample_bits = 8;
1030 memcpy(wav_chunk.id, "data", 4);
1031 wav_chunk.size = length - sizeof(wav_header) - sizeof(wav_chunk);
1033 rec_fio->Fseek(0, FILEIO_SEEK_SET);
1034 rec_fio->Fwrite(&wav_header, sizeof(wav_header), 1);
1035 rec_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
1038 // FUJITSU FM-7 series tape image
1040 #define T77_PUT_SIGNAL(signal, len) { \
1042 while(remain > 0) { \
1043 if(buffer != NULL) { \
1044 buffer[ptr++] = (signal) ? 0xff : 0x00; \
1052 int DATAREC::load_t77_image()
1055 sample_rate = (int)(1000000.0 / sample_usec + 0.5);
1060 int file_size = (int)play_fio->FileLength();
1062 if(file_size <= 0) {
1063 return 0; // over 2GB
1065 play_fio->Fseek(0, FILEIO_SEEK_SET);
1066 play_fio->Fread(tmpbuf, 16, 1);
1068 if(strcmp((char *)tmpbuf, "XM7 TAPE IMAGE 0") != 0) {
1073 while(file_size > 0) {
1074 uint16_t h = play_fio->FgetUint8();
1075 uint16_t l = play_fio->FgetUint8();
1076 uint16_t v = h * 256 + l;
1078 if((file_size -= 2) < 0) {
1082 T77_PUT_SIGNAL((h & 0x80) != 0, v & 0x7fff);
1088 // SHARP X1 series tape image
1091 new tape file format for t-tune (from tape_fmt.txt)
1094 00H : 4 :
\8e¯
\95Ê
\83C
\83\93\83f
\83b
\83N
\83X "TAPE"
1095 04H : 17 :
\83e
\81[
\83v
\82Ì
\96¼
\91O(asciiz)
1096 15H : 5 :
\83\8a\83U
\81[
\83u
1097 1AH : 1 :
\83\89\83C
\83g
\83v
\83\8d\83e
\83N
\83g
\83m
\83b
\83`(00H=
\8f\91\82«
\8d\9e\82Ý
\89Â
\81A10H=
\8f\91\82«
\8d\9e\82Ý
\8bÖ
\8e~
\81j
1098 1BH : 1 :
\8bL
\98^
\83t
\83H
\81[
\83}
\83b
\83g
\82Ì
\8eí
\97Þ(01H=
\92è
\91¬
\83T
\83\93\83v
\83\8a\83\93\83O
\95û
\96@
\81j
1099 1CH : 4 :
\83T
\83\93\83v
\83\8a\83\93\83O
\8eü
\94g
\90\94(
\82g
\82\9a\92P
\88Ê
\81j
1100 20H : 4 :
\83e
\81[
\83v
\83f
\81[
\83^
\82Ì
\83T
\83C
\83Y
\81i
\83r
\83b
\83g
\92P
\88Ê
\81j
1101 24H : 4 :
\83e
\81[
\83v
\82Ì
\88Ê
\92u
\81i
\83r
\83b
\83g
\92P
\88Ê
\81j
1102 28H : ? :
\83e
\81[
\83v
\82Ì
\83f
\81[
\83^
1105 int DATAREC::load_tap_image()
1108 play_fio->Fseek(0, FILEIO_SEEK_END);
1109 //int file_size = play_fio->Ftell();
1110 play_fio->Fseek(0, FILEIO_SEEK_SET);
1114 play_fio->Fread(header, 4, 1);
1116 if(header[0] == 'T' && header[1] == 'A' && header[2] == 'P' && header[3] == 'E') {
1117 // skip name, reserved, write protect notch
1118 play_fio->Fseek(17 + 5 + 1, FILEIO_SEEK_CUR);
1120 if(play_fio->Fgetc() != 0x01) {
1121 // unknown data format
1125 play_fio->Fread(header, 4, 1);
1126 sample_rate = header[0] | (header[1] << 8) | (header[2] << 16) | (header[3] << 24);
1127 sample_usec = 1000000. / sample_rate;
1129 play_fio->Fread(header, 4, 1);
1131 play_fio->Fread(header, 4, 1);
1134 sample_rate = header[0] | (header[1] << 8) | (header[2] << 16) | (header[3] << 24);
1135 sample_usec = 1000000. / sample_rate;
1140 while((data = play_fio->Fgetc()) != EOF) {
1141 for(int i = 0, bit = 0x80; i < 8; i++, bit >>= 1) {
1142 if(buffer != NULL) {
1143 buffer[ptr] = ((data & bit) != 0) ? 255 : 0;
1151 // SHARP MZ series tape image
1153 //#define MZT_PUT_SIGNAL(signal, len) { \
1154 // int remain = len; \
1155 // while(remain > 0) { \
1156 // if(buffer != NULL) { \
1157 // buffer[ptr++] = ((signal != 0) ? 0x80 : 0) | min(remain, 0x7f); \
1161 // remain -= min(remain, 0x7f); \
1165 #define MZT_PUT_SIGNAL(signal, len) { \
1167 while(remain > 0) { \
1168 if(buffer != NULL) { \
1169 buffer[ptr++] = (signal != 0) ? 0xff : 0; \
1177 #define MZT_PUT_BIT(bit, len) { \
1178 for(int l = 0; l < (len); l++) { \
1180 MZT_PUT_SIGNAL(1, len1); \
1181 MZT_PUT_SIGNAL(0, len2); \
1183 MZT_PUT_SIGNAL(1, len3); \
1184 MZT_PUT_SIGNAL(0, len4); \
1189 #define MZT_PUT_BYTE(byte) { \
1190 MZT_PUT_BIT(1, 1); \
1191 for(int j = 0; j < 8; j++) { \
1192 if((byte) & (0x80 >> j)) { \
1193 MZT_PUT_BIT(1, 1); \
1196 MZT_PUT_BIT(0, 1); \
1201 #define MZT_PUT_BLOCK(buf, len) { \
1203 for(int i = 0; i < (len); i++) { \
1204 MZT_PUT_BYTE((buf)[i]); \
1206 uint8_t hi = (count >> 8) & 0xff; \
1207 uint8_t lo = (count >> 0) & 0xff; \
1212 int DATAREC::load_mzt_image()
1214 int len1, len2, len3, len4;
1215 sample_rate = 48000;
1216 sample_usec = 1000000. / sample_rate;
1218 len1 = len2 = (int)(120.0 / 16.0 * sample_rate / 22050.0 + 0.5);
1219 len3 = len4 = (int)(60.0 / 16.0 * sample_rate / 22050.0 + 0.5);
1221 len1 = (int)(24.0 * sample_rate / 48000.0 + 0.5);
1222 len2 = (int)(29.0 * sample_rate / 48000.0 + 0.5);
1223 len3 = (int)(11.0 * sample_rate / 48000.0 + 0.5);
1224 len4 = (int)(15.0 * sample_rate / 48000.0 + 0.5);
1229 play_fio->Fseek(0, FILEIO_SEEK_END);
1230 int file_size = play_fio->Ftell();
1231 play_fio->Fseek(0, FILEIO_SEEK_SET);
1235 while(file_size > 128) {
1237 uint8_t header[128], ram[0x20000];
1238 play_fio->Fread(header, sizeof(header), 1);
1239 file_size -= sizeof(header);
1241 uint16_t size = header[0x12] | (header[0x13] << 8);
1242 uint16_t offs = header[0x14] | (header[0x15] << 8);
1243 memset(ram, 0, sizeof(ram));
1244 play_fio->Fread(ram + offs, size, 1);
1246 //#if defined(_MZ80K) || defined(_MZ700) || defined(_MZ1200) || defined(_MZ1500)
1248 // apply mz700win patch
1249 if(header[0x40] == 'P' && header[0x41] == 'A' && header[0x42] == 'T' && header[0x43] == ':') {
1250 int patch_ofs = 0x44;
1251 for(; patch_ofs < 0x80; ) {
1252 uint16_t patch_addr = header[patch_ofs] | (header[patch_ofs + 1] << 8);
1254 if(patch_addr == 0xffff) {
1257 int patch_len = header[patch_ofs++];
1258 for(int i = 0; i < patch_len; i++) {
1259 ram[patch_addr + i] = header[patch_ofs++];
1262 for(int i = 0x40; i < patch_ofs; i++) {
1268 MZT_PUT_SIGNAL(0, sample_rate);
1269 //#if defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200)
1272 MZT_PUT_BIT(0, 22000);
1275 MZT_PUT_BLOCK(header, 128);
1277 MZT_PUT_SIGNAL(1, (int)(22.0 * sample_rate / 22050.0 + 0.5));
1278 MZT_PUT_SIGNAL(0, (int)(22.0 * sample_rate / 22050.0 + 0.5));
1279 MZT_PUT_SIGNAL(0, sample_rate);
1280 MZT_PUT_BIT(0, 11000);
1283 MZT_PUT_BLOCK(ram + offs, size);
1287 // format info written in
\8e\8e\8c±
\82É
\8fo
\82éX1
1288 MZT_PUT_BIT(0, 10000);
1292 MZT_PUT_BLOCK(header, 128);
1294 MZT_PUT_BIT(0, 256);
1295 MZT_PUT_BLOCK(header, 128);
1297 MZT_PUT_SIGNAL(0, sample_rate);
1298 MZT_PUT_BIT(0, 10000);
1302 MZT_PUT_BLOCK(ram + offs, size);
1310 // NEC PC-6001/6601 series tape image
1312 #define P6_PUT_1200HZ() { \
1313 if(buffer != NULL) { \
1314 for(int p = 0; p < 20; p++) buffer[ptr++] = 0xff; \
1315 for(int p = 0; p < 20; p++) buffer[ptr++] = 0x00; \
1321 #define P6_PUT_2400HZ() { \
1322 if(buffer != NULL) { \
1323 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1324 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1330 #define P6_PUT_2400HZ_X2() { \
1331 if(buffer != NULL) { \
1332 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1333 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1334 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1335 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1341 int DATAREC::load_p6_image(bool is_p6t)
1343 sample_rate = 48000;
1344 sample_usec = 1000000. / sample_rate;
1346 int ptr = 0, remain = 0x10000, data;
1348 // get info block offset
1349 play_fio->Fseek(-4, FILEIO_SEEK_END);
1350 int length = play_fio->FgetInt32();
1352 play_fio->Fseek(length, FILEIO_SEEK_SET);
1353 char id_p = play_fio->Fgetc();
1354 char id_6 = play_fio->Fgetc();
1355 uint8_t ver = play_fio->FgetUint8();
1356 if(id_p == 'P' && id_6 == '6' && ver == 2) {
1357 uint8_t blocks = play_fio->FgetUint8();
1359 play_fio->FgetUint8();
1360 play_fio->FgetUint8();
1361 play_fio->FgetUint8();
1362 uint16_t cmd = play_fio->FgetUint16();
1363 play_fio->Fseek(cmd, FILEIO_SEEK_CUR);
1364 uint16_t exp = play_fio->FgetUint16();
1365 play_fio->Fseek(exp, FILEIO_SEEK_CUR);
1366 // check 1st data block
1367 char id_t = play_fio->Fgetc();
1368 char id_i = play_fio->Fgetc();
1369 if(id_t == 'T' && id_i == 'I') {
1370 play_fio->FgetUint8();
1371 play_fio->Fseek(16, FILEIO_SEEK_CUR);
1372 uint16_t baud = play_fio->FgetUint16(); // 600 or 1200
1373 sample_rate = sample_rate * baud / 1200;
1374 sample_usec = 1000000. / sample_rate;
1377 remain = min(length, 0x10000);
1380 play_fio->Fseek(0, FILEIO_SEEK_SET);
1382 for(int i = 0; i < 9600; i++) {
1385 for(int i = 0; i < 16; i++) {
1386 data = play_fio->Fgetc();
1388 for(int j = 0; j < 8; j++) {
1389 if(data & (1 << j)) {
1400 // for(int i = 0; i < 1280; i++) {
1401 for(int i = 0; i < 2400; i++) {
1404 while((data = play_fio->Fgetc()) != EOF && remain > 0) {
1406 for(int j = 0; j < 8; j++) {
1407 if(data & (1 << j)) {
1419 for(int i = 0; i < 16; i++) {
1421 for(int j = 0; j < 8; j++) {
1432 // HITACH BASIC Master Jr tape image (bm2)
1434 #define BMJR_PUT_1200HZ_X4() { \
1435 if(buffer != NULL) { \
1436 for(int k = 0; k < 4; k++) { \
1437 for(int p = 0; p < 20; p++) buffer[ptr++] = 0xff; \
1438 for(int p = 0; p < 20; p++) buffer[ptr++] = 0x00; \
1445 #define BMJR_PUT_2400HZ_X8() { \
1446 if(buffer != NULL) { \
1447 for(int k = 0; k < 8; k++) { \
1448 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1449 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1456 int DATAREC::load_bmjr_image()
1458 sample_rate = 48000;
1459 sample_usec = 1000000. / sample_rate;
1461 play_fio->Fseek(0, FILEIO_SEEK_SET);
1464 while((data = play_fio->Fgetc()) != EOF) {
1466 BMJR_PUT_1200HZ_X4();
1468 for(int j = 0; j < 8; j++) {
1469 if(data & (1 << j)) {
1470 BMJR_PUT_2400HZ_X8();
1472 BMJR_PUT_1200HZ_X4();
1476 BMJR_PUT_2400HZ_X8();
1477 BMJR_PUT_2400HZ_X8();
1482 // standard cas image for my emulator
1484 static const uint8_t msx_cas_header[8] = {0x1f, 0xa6, 0xde, 0xba, 0xcc, 0x13, 0x7d, 0x74};
1486 int DATAREC::load_cas_image()
1488 sample_rate = 48000;
1489 sample_usec = 1000000. / sample_rate;
1491 // SORD m5 or NEC PC-6001 series cas image ?
1492 static const uint8_t momomomomomo[6] = {0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3};
1493 uint8_t tmp_header[8];
1494 play_fio->Fseek(0, FILEIO_SEEK_SET);
1495 play_fio->Fread(tmp_header, sizeof(tmp_header), 1);
1497 if(memcmp(tmp_header, "SORDM5", 6) == 0) {
1498 return load_m5_cas_image();
1499 } else if(memcmp(tmp_header, msx_cas_header, 8) == 0) {
1500 return load_msx_cas_image();
1501 } else if(memcmp(tmp_header, momomomomomo, 6) == 0) {
1502 return load_p6_image(false);
1505 // this is the standard cas image for my emulator
1506 play_fio->Fseek(0, FILEIO_SEEK_SET);
1508 while((data = play_fio->Fgetc()) != EOF) {
1509 for(int i = 0; i < (data & 0x7f); i++) {
1510 if(buffer != NULL) {
1511 buffer[ptr] = (data & 0x80) ? 255 : 0;
1519 // SORD M5 tape image
1521 #define M5_PUT_BIT(val, len) { \
1523 while(remain > 0) { \
1524 if(buffer != NULL) { \
1525 buffer[ptr] = val ? 0 : 0xff; \
1532 #define M5_PUT_BYTE(data) { \
1533 for(int j = 0; j < 10; j++) { \
1534 int bit = (j == 0) ? 1 : (j == 1) ? 0 : ((data >> (j - 2)) & 1); \
1536 M5_PUT_BIT(0xff, 8); \
1537 M5_PUT_BIT(0x00, 7); \
1539 M5_PUT_BIT(0xff, 16); \
1540 M5_PUT_BIT(0x00, 14); \
1545 int DATAREC::load_m5_cas_image()
1547 play_fio->Fseek(16, FILEIO_SEEK_SET);
1548 int ptr = 0, block_type;
1550 while((block_type = play_fio->Fgetc()) != EOF) {
1551 if(block_type != 'H' && block_type != 'D') {
1554 int block_size = play_fio->Fgetc();
1556 if(block_type == 'H') {
1557 M5_PUT_BIT(0x00, 1);
1559 for(int i = 0; i < (block_type == 'H' ? 945 : 59); i++) {
1560 M5_PUT_BIT(0xff, 8);
1561 M5_PUT_BIT(0x00, 7);
1563 M5_PUT_BYTE(block_type);
1564 M5_PUT_BYTE(block_size);
1566 for(int i = 0; i < ((block_size == 0) ? 0x101 : (block_size + 1)); i++) {
1567 uint8_t data = play_fio->Fgetc();
1570 M5_PUT_BIT(0xff, 8);
1571 M5_PUT_BIT(0x00, 7);
1573 M5_PUT_BIT(0x00, 1);
1577 // ASCII MSX tape image (fMSX)
1578 // MAME/MESS /src/lib/formats/fmsx_cas.c by Mr.Sean Young
1580 #define CAS_PERIOD (16)
1581 #define CAS_HEADER_PERIODS (4000)
1582 #define CAS_EMPTY_PERIODS (1000)
1584 int DATAREC::load_msx_cas_image()
1586 sample_rate = 22050;
1587 sample_usec = 1000000. / sample_rate;
1589 play_fio->Fseek(0, FILEIO_SEEK_END);
1590 int cas_size = play_fio->Ftell();
1591 uint8_t *bytes = (uint8_t *)malloc(cas_size);
1592 play_fio->Fseek(0, FILEIO_SEEK_SET);
1593 play_fio->Fread(bytes, cas_size, 1);
1595 int cas_pos, bit, state = 1, samples_pos, size, n, i, p;
1600 while(/*samples_pos < sample_count && */cas_pos < cas_size) {
1601 /* Check if we need to output a header */
1602 if(cas_pos + 8 < cas_size) {
1603 if(!memcmp( bytes + cas_pos, msx_cas_header, 8)) {
1604 /* Write CAS_EMPTY_PERIODS of silence */
1605 n = CAS_EMPTY_PERIODS * CAS_PERIOD;
1607 if(buffer != NULL) {
1608 buffer[samples_pos] = 0;
1612 /* Write CAS_HEADER_PERIODS of header (high frequency) */
1613 for(i = 0; i < CAS_HEADER_PERIODS * 4 ; i++) {
1614 for(n = 0; n < CAS_PERIOD / 4; n++) {
1615 if(buffer != NULL) {
1616 buffer[samples_pos + n] = (state ? 0xff : 0);
1619 samples_pos += CAS_PERIOD / 4 ;
1626 for(i = 0; i <= 11; i++) {
1630 bit = (bytes[cas_pos] & (1 << (i - 1) ) );
1635 /* write this one bit */
1636 for(n = 0; n < (bit ? 4 : 2); n++) {
1637 size = (bit ? CAS_PERIOD / 4 : CAS_PERIOD / 2);
1638 for(p = 0; p < size; p++) {
1639 if(buffer != NULL) {
1640 buffer[samples_pos + p] = (state ? 0xff : 0);
1644 samples_pos += size;
1653 void DATAREC::mix(int32_t* buffer, int cnt)
1655 int32_t* buffer_tmp = buffer;
1657 if(config.sound_play_tape && pcm_changed && remote && (play || rec) && ff_rew == 0) {
1658 bool signal = ((play && in_signal) || (rec && out_signal));
1660 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
1662 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
1664 int clocks = pcm_positive_clocks + pcm_negative_clocks;
1665 int sample = clocks ? (pcm_max_vol * pcm_positive_clocks - pcm_max_vol * pcm_negative_clocks) / clocks : signal ? pcm_max_vol : -pcm_max_vol;
1667 pcm_last_vol_l = apply_volume(sample, pcm_volume_l);
1668 pcm_last_vol_r = apply_volume(sample, pcm_volume_r);
1670 for(int i = 0; i < cnt; i++) {
1671 *buffer++ += pcm_last_vol_l; // L
1672 *buffer++ += pcm_last_vol_r; // R
1674 } else if(pcm_last_vol_l || pcm_last_vol_r) {
1675 // suppress petite noise when go to mute
1676 for(int i = 0; i < cnt; i++) {
1677 *buffer++ += pcm_last_vol_l; // L
1678 *buffer++ += pcm_last_vol_r; // R
1680 if(pcm_last_vol_l > 0) {
1682 } else if(pcm_last_vol_l < 0) {
1685 if(pcm_last_vol_r > 0) {
1687 } else if(pcm_last_vol_r < 0) {
1692 pcm_prev_clock = get_current_clock();
1693 pcm_positive_clocks = pcm_negative_clocks = 0;
1695 //#ifdef DATAREC_SOUND
1696 if(__DATAREC_SOUND) {
1697 if(/*config.sound_play_tape && */remote && play && ff_rew == 0) {
1698 sound_last_vol_l = apply_volume(sound_sample, sound_volume_l);
1699 sound_last_vol_r = apply_volume(sound_sample, sound_volume_r);
1700 buffer = buffer_tmp; // restore
1701 for(int i = 0; i < cnt; i++) {
1702 *buffer += sound_last_vol_l; // L
1703 *buffer += sound_last_vol_r; // R
1705 } else if(sound_last_vol_l || sound_last_vol_r) {
1706 // suppress petite noise when go to mute
1707 for(int i = 0; i < cnt; i++) {
1708 *buffer++ += sound_last_vol_l; // L
1709 *buffer++ += sound_last_vol_r; // R
1711 if(sound_last_vol_l > 0) {
1713 } else if(sound_last_vol_l < 0) {
1716 if(sound_last_vol_r > 0) {
1718 } else if(sound_last_vol_r < 0) {
1727 void DATAREC::set_volume(int ch, int decibel_l, int decibel_r)
1730 pcm_volume_l = decibel_to_volume(decibel_l);
1731 pcm_volume_r = decibel_to_volume(decibel_r);
1732 //#ifdef DATAREC_SOUND
1733 } else if(ch == 1) {
1734 if(__DATAREC_SOUND) {
1735 sound_volume_l = decibel_to_volume(decibel_l);
1736 sound_volume_r = decibel_to_volume(decibel_r);
1742 double DATAREC::get_ave_hi_freq()
1744 if(ave_hi_freq == 0 && play && is_wav) {
1745 bool prev_signal = false;
1746 int positive = 0, negative = 0, pulse_count = 0;
1748 double base_usec = 1000000.0 / (double)sample_rate;
1750 for(int i=0; i < buffer_length; i++) {
1751 bool next_signal = ((buffer[i] & 0x80) != 0);
1752 if(!prev_signal && next_signal) {
1753 double usec = base_usec * (positive + negative);
1754 if(316.667 <= usec && usec < 516.667) {
1757 } else if(633.333 <= usec && usec < 1033.333) {
1761 positive = negative = 0;
1768 prev_signal = next_signal;
1770 if(sum != 0 && pulse_count != 0) {
1771 double average = sum / pulse_count;
1772 ave_hi_freq = 1000000.0 / average;
1775 if(ave_hi_freq == 0) {
1781 void DATAREC::update_config()
1783 if(d_noise_play != NULL) {
1784 d_noise_play->set_mute(!config.sound_noise_cmt);
1786 if(d_noise_stop != NULL) {
1787 d_noise_stop->set_mute(!config.sound_noise_cmt);
1789 if(d_noise_fast != NULL) {
1790 d_noise_fast->set_mute(!config.sound_noise_cmt);
1792 update_realtime_render();
1795 #define STATE_VERSION 8
1797 void DATAREC::save_state(FILEIO* state_fio)
1799 state_fio->FputUint32(STATE_VERSION);
1800 state_fio->FputInt32(this_device_id);
1802 state_fio->FputBool(play);
1803 state_fio->FputBool(rec);
1804 state_fio->FputBool(remote);
1805 state_fio->FputBool(trigger);
1806 state_fio->Fwrite(rec_file_path, sizeof(rec_file_path), 1);
1807 if(rec && rec_fio->IsOpened()) {
1808 int length_tmp = (int)rec_fio->Ftell();
1809 rec_fio->Fseek(0, FILEIO_SEEK_SET);
1810 state_fio->FputInt32(length_tmp);
1811 while(length_tmp != 0) {
1812 uint8_t buffer_tmp[1024];
1813 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
1814 rec_fio->Fread(buffer_tmp, length_rw, 1);
1815 state_fio->Fwrite(buffer_tmp, length_rw, 1);
1816 length_tmp -= length_rw;
1819 state_fio->FputInt32(0);
1821 state_fio->FputInt32(ff_rew);
1822 state_fio->FputBool(in_signal);
1823 state_fio->FputBool(out_signal);
1824 state_fio->FputUint32(prev_clock);
1825 state_fio->FputInt32(positive_clocks);
1826 state_fio->FputInt32(negative_clocks);
1827 state_fio->FputInt32(signal_changed);
1828 state_fio->FputInt32(register_id);
1829 state_fio->FputBool(realtime);
1830 state_fio->FputInt32(sample_rate);
1831 state_fio->FputDouble(sample_usec);
1832 state_fio->FputInt32(buffer_ptr);
1834 state_fio->FputInt32(buffer_length);
1835 state_fio->Fwrite(buffer, buffer_length, 1);
1837 state_fio->FputInt32(0);
1840 state_fio->FputInt32(buffer_length);
1841 state_fio->Fwrite(buffer_bak, buffer_length, 1);
1843 state_fio->FputInt32(0);
1845 //#ifdef DATAREC_SOUND
1846 if(__DATAREC_SOUND) {
1848 state_fio->FputInt32(sound_buffer_length);
1849 state_fio->Fwrite(sound_buffer, sound_buffer_length, 1);
1851 state_fio->FputInt32(0);
1853 state_fio->FputInt16(sound_sample);
1856 state_fio->FputBool(is_wav);
1857 state_fio->FputBool(is_tap);
1858 state_fio->FputBool(is_t77);
1860 state_fio->FputInt32(apss_buffer_length);
1861 state_fio->Fwrite(apss_buffer, apss_buffer_length, 1);
1863 state_fio->FputInt32(0);
1865 state_fio->FputInt32(apss_ptr);
1866 state_fio->FputInt32(apss_count);
1867 state_fio->FputInt32(apss_remain);
1868 state_fio->FputBool(apss_signals);
1869 state_fio->FputInt32(pcm_changed);
1870 state_fio->FputUint32(pcm_prev_clock);
1871 state_fio->FputInt32(pcm_positive_clocks);
1872 state_fio->FputInt32(pcm_negative_clocks);
1875 bool DATAREC::load_state(FILEIO* state_fio)
1879 if(state_fio->FgetUint32() != STATE_VERSION) {
1882 if(state_fio->FgetInt32() != this_device_id) {
1885 play = state_fio->FgetBool();
1886 rec = state_fio->FgetBool();
1887 remote = state_fio->FgetBool();
1888 trigger = state_fio->FgetBool();
1889 state_fio->Fread(rec_file_path, sizeof(rec_file_path), 1);
1890 int length_tmp = state_fio->FgetInt32();
1892 rec_fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
1893 while(length_tmp != 0) {
1894 uint8_t buffer_tmp[1024];
1895 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
1896 state_fio->Fread(buffer_tmp, length_rw, 1);
1897 if(rec_fio->IsOpened()) {
1898 rec_fio->Fwrite(buffer_tmp, length_rw, 1);
1900 length_tmp -= length_rw;
1903 ff_rew = state_fio->FgetInt32();
1904 in_signal = state_fio->FgetBool();
1905 out_signal = state_fio->FgetBool();
1906 prev_clock = state_fio->FgetUint32();
1907 positive_clocks = state_fio->FgetInt32();
1908 negative_clocks = state_fio->FgetInt32();
1909 signal_changed = state_fio->FgetInt32();
1910 register_id = state_fio->FgetInt32();
1911 realtime = state_fio->FgetBool();
1912 sample_rate = state_fio->FgetInt32();
1913 sample_usec = state_fio->FgetDouble();
1914 buffer_ptr = state_fio->FgetInt32();
1915 if((buffer_length = state_fio->FgetInt32()) != 0) {
1916 buffer = (uint8_t *)malloc(buffer_length);
1917 state_fio->Fread(buffer, buffer_length, 1);
1919 if((length_tmp = state_fio->FgetInt32()) != 0) {
1920 buffer_bak = (uint8_t *)malloc(length_tmp);
1921 state_fio->Fread(buffer_bak, length_tmp, 1);
1923 //#ifdef DATAREC_SOUND
1924 if(__DATAREC_SOUND) {
1925 if((sound_buffer_length = state_fio->FgetInt32()) != 0) {
1926 sound_buffer = (int16_t *)malloc(sound_buffer_length);
1927 state_fio->Fread(sound_buffer, sound_buffer_length, 1);
1929 sound_sample = state_fio->FgetInt16();
1932 is_wav = state_fio->FgetBool();
1933 is_tap = state_fio->FgetBool();
1934 is_t77 = state_fio->FgetBool();
1935 if((apss_buffer_length = state_fio->FgetInt32()) != 0) {
1936 apss_buffer = (bool *)malloc(apss_buffer_length);
1937 state_fio->Fread(apss_buffer, apss_buffer_length, 1);
1939 apss_ptr = state_fio->FgetInt32();
1940 apss_count = state_fio->FgetInt32();
1941 apss_remain = state_fio->FgetInt32();
1942 apss_signals = state_fio->FgetBool();
1943 pcm_changed = state_fio->FgetInt32();
1944 pcm_prev_clock = state_fio->FgetUint32();
1945 pcm_positive_clocks = state_fio->FgetInt32();
1946 pcm_negative_clocks = state_fio->FgetInt32();
1949 pcm_last_vol_l = pcm_last_vol_r = 0;
1950 //#ifdef DATAREC_SOUND
1951 sound_last_vol_l = sound_last_vol_r = 0;