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, 0x00, sizeof(rec_file_path));
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);
97 // TRY: Not close even resetting.20180630 K.O
98 // ToDo: Resume tape-counter after re-initializing VM.
104 write_signals(&outputs_ear, 0);
107 pcm_prev_clock = get_current_clock();
108 pcm_positive_clocks = pcm_negative_clocks = 0;
112 void DATAREC::release()
120 void DATAREC::write_signal(int id, uint32_t data, uint32_t mask)
122 bool signal = ((data & mask) != 0);
124 if(id == SIG_DATAREC_MIC) {
125 if(out_signal != signal) {
129 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
131 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
133 pcm_prev_clock = get_current_clock();
137 if(prev_clock != 0) {
139 positive_clocks += get_passed_clock(prev_clock);
141 negative_clocks += get_passed_clock(prev_clock);
143 prev_clock = get_current_clock();
147 } else if(id == SIG_DATAREC_REMOTE) {
150 } else if(id == SIG_DATAREC_TRIG) {
151 // L->H: remote signal is switched
152 if(signal && !trigger) {
160 void DATAREC::event_frame()
165 //#ifdef DATAREC_SOUND
166 if(__DATAREC_SOUND) {
167 if(remote && (play || rec) && ff_rew == 0 && signal_changed > 10 && !config.sound_play_tape && sound_sample == 0) {
168 request_skip_frames();
172 if(remote && (play || rec) && ff_rew == 0 && signal_changed > 10 && !config.sound_play_tape) {
174 request_skip_frames();
180 void DATAREC::event_callback(int event_id, int err)
182 if(event_id == EVENT_SIGNAL) {
185 my_stprintf_s(message, 1024, _T("Fast Forward (%d %%)"), get_tape_position());
186 } else if(ff_rew < 0) {
187 my_stprintf_s(message, 1024, _T("Fast Rewind (%d %%)"), get_tape_position());
189 my_stprintf_s(message, 1024, _T("Play (%d %%)"), get_tape_position());
191 bool signal = in_signal;
193 if(buffer_ptr >= 0 && buffer_ptr < buffer_length) {
195 signal = ((buffer[buffer_ptr] & 0x80) != 0);
199 //#ifdef DATAREC_SOUND
200 if(__DATAREC_SOUND) {
201 if(sound_buffer != NULL && ff_rew == 0) {
202 sound_sample = sound_buffer[buffer_ptr];
210 if((buffer_ptr = max(buffer_ptr - 1, 0)) == 0) {
211 set_remote(false); // top of tape
215 if((buffer_ptr = min(buffer_ptr + 1, buffer_length)) == buffer_length) {
216 set_remote(false); // end of tape
223 if((buffer_bak != NULL) && (buffer != NULL)) {
224 my_memcpy(buffer, buffer_bak, buffer_length);
227 set_remote(false); // top of tape
230 while(buffer_ptr < buffer_length) {
231 if((buffer[buffer_ptr] & 0x7f) == 0) {
232 if(++buffer_ptr == buffer_length) {
233 set_remote(false); // end of tape
237 signal = ((buffer[buffer_ptr] & 0x80) != 0);
239 signal = ((buffer[buffer_ptr] & 0x80) != 0);
240 uint8_t tmp = buffer[buffer_ptr];
241 buffer[buffer_ptr] = (tmp & 0x80) | ((tmp & 0x7f) - 1);
246 set_remote(false); // end of tape
251 // notify the signal is changed
252 if(signal != in_signal) {
254 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
256 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
258 pcm_prev_clock = get_current_clock();
263 write_signals(&outputs_ear, in_signal ? 0xffffffff : 0);
266 if(apss_buffer != NULL) {
267 int ptr = (apss_ptr++) % (sample_rate * 2);
268 if(apss_buffer[ptr]) {
274 apss_buffer[ptr] = in_signal;
276 if(apss_ptr >= sample_rate * 2) {
277 double rate = (double)apss_count / (double)(sample_rate * 2);
278 if(rate > 0.9 || rate < 0.1) {
280 if(apss_remain > 0) {
282 } else if(apss_remain < 0) {
285 write_signals(&outputs_apss, 0xffffffff);
286 apss_signals = false;
290 write_signals(&outputs_apss, 0);
296 } else if(rec && buffer != NULL) {
298 positive_clocks += get_passed_clock(prev_clock);
300 negative_clocks += get_passed_clock(prev_clock);
303 if(positive_clocks != 0 || negative_clocks != 0) {
304 buffer[buffer_ptr] = (255 * positive_clocks) / (positive_clocks + negative_clocks);
306 buffer[buffer_ptr] = 0;
308 if(++buffer_ptr >= buffer_length) {
310 for(int i = 0; i < buffer_length; i += 8) {
312 for(int j = 0, bit = 0x80; j < 8; j++, bit >>= 1) {
313 if(i + j < buffer_length && buffer[i + j] >= 0x80) {
317 rec_fio->FputUint8(val);
320 rec_fio->Fwrite(buffer, buffer_length, 1);
326 bool signal = (positive_clocks > negative_clocks);
327 uint16_t data = (buffer[buffer_ptr] << 8) | buffer[buffer_ptr + 1];
328 if(signal != ((data & 0x8000) != 0)) {
329 if((buffer_ptr += 2) >= buffer_length) {
330 rec_fio->Fwrite(buffer, buffer_length, 1);
334 data = signal ? 0x8001 : 0x0001;
335 } else if((data & 0x7fff) < 0x7fff) {
338 buffer[buffer_ptr + 0] = data >> 8;
339 buffer[buffer_ptr + 1] = data & 0xff;
341 bool prev_signal = ((buffer[buffer_ptr] & 0x80) != 0);
342 bool cur_signal = (positive_clocks > negative_clocks);
343 if(prev_signal != cur_signal || (buffer[buffer_ptr] & 0x7f) == 0x7f) {
344 if(++buffer_ptr >= buffer_length) {
345 rec_fio->Fwrite(buffer, buffer_length, 1);
349 buffer[buffer_ptr] = cur_signal ? 0x80 : 0;
351 buffer[buffer_ptr]++;
353 prev_clock = get_current_clock();
354 positive_clocks = negative_clocks = 0;
359 void DATAREC::set_remote(bool value)
361 if(remote != value) {
363 if(d_noise_play != NULL) {
364 d_noise_play->play();
366 if(d_noise_fast != NULL && ff_rew != 0) {
367 d_noise_fast->play();
370 if(d_noise_stop != NULL) {
371 d_noise_stop->play();
373 if(d_noise_fast != NULL) {
374 d_noise_fast->stop();
382 void DATAREC::set_ff_rew(int value)
384 if(ff_rew != value) {
385 if(register_id != -1) {
386 cancel_event(this, register_id);
390 if(d_noise_fast != NULL && remote) {
391 d_noise_fast->play();
394 if(d_noise_fast != NULL) {
395 d_noise_fast->stop();
399 apss_signals = false;
404 bool DATAREC::do_apss(int value)
411 set_ff_rew(value > 0 ? 1 : -1);
414 while(apss_remain != 0 && remote) {
415 event_callback(EVENT_SIGNAL, 0);
417 result = (apss_remain == 0);
426 my_stprintf_s(message, 1024, _T("APSS Forward (%d %%)"), get_tape_position());
428 my_stprintf_s(message, 1024, _T("APSS Forward"));
432 my_stprintf_s(message, 1024, _T("APSS Rewind (%d %%)"), get_tape_position());
434 my_stprintf_s(message, 1024, _T("APSS Rewind"));
440 void DATAREC::update_event()
442 if(remote && (play || rec)) {
443 if(register_id == -1) {
445 register_event(this, EVENT_SIGNAL, sample_usec / __DATAREC_FAST_FWD_SPEED, true, ®ister_id);
446 } else if(ff_rew < 0) {
447 register_event(this, EVENT_SIGNAL, sample_usec / __DATAREC_FAST_REW_SPEED, true, ®ister_id);
450 my_stprintf_s(message, 1024, _T("Record"));
452 register_event(this, EVENT_SIGNAL, sample_usec, true, ®ister_id);
454 prev_clock = get_current_clock();
455 positive_clocks = negative_clocks = 0;
458 if(register_id != -1) {
459 cancel_event(this, register_id);
462 if(buffer_ptr >= buffer_length) {
463 my_stprintf_s(message, 1024, _T("Stop (End-of-Tape)"));
464 } else if(buffer_ptr <= 0) {
465 my_stprintf_s(message, 1024, _T("Stop (Beginning-of-Tape)"));
467 my_stprintf_s(message, 1024, _T("Stop (%d %%)"), get_tape_position());
470 my_stprintf_s(message, 1024, _T("Stop"));
477 //#ifdef DATAREC_SOUND
478 if(__DATAREC_SOUND) {
479 if(!(play && remote)) {
484 write_signals(&outputs_remote, remote ? 0xffffffff : 0);
485 write_signals(&outputs_rotate, (register_id != -1) ? 0xffffffff : 0);
486 write_signals(&outputs_end, (buffer_ptr == buffer_length) ? 0xffffffff : 0);
487 write_signals(&outputs_top, (buffer_ptr == 0) ? 0xffffffff : 0);
489 update_realtime_render();
492 void DATAREC::update_realtime_render()
494 bool value = (remote && (play || rec) && ff_rew == 0 && config.sound_play_tape);
496 if(realtime != value) {
497 set_realtime_render(this, value);
502 bool DATAREC::play_tape(const _TCHAR* file_path)
506 if(play_fio->Fopen(file_path, FILEIO_READ_BINARY)) {
507 if(check_file_extension(play_fio->FilePath(), _T(".wav")) || check_file_extension(play_fio->FilePath(), _T(".mti"))) {
508 // standard PCM wave file
509 if((buffer_length = load_wav_image(0)) != 0) {
510 play = is_wav = true;
512 } else if(check_file_extension(play_fio->FilePath(), _T(".t77"))) {
513 // FUJITSU FM-7 series tape image
514 if((buffer_length = load_t77_image()) != 0) {
515 buffer = (uint8_t *)malloc(buffer_length);
517 play = is_wav = true;
519 } else if(check_file_extension(play_fio->FilePath(), _T(".tap"))) {
520 // SHARP X1 series tape image
521 if((buffer_length = load_tap_image()) != 0) {
522 buffer = (uint8_t *)malloc(buffer_length);
524 play = is_wav = true;
526 } 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"))) {
527 // SHARP MZ series tape image
528 if((buffer_length = load_mzt_image()) != 0) {
529 buffer = (uint8_t *)malloc(buffer_length);
531 play = is_wav = true;
533 } else if(check_file_extension(play_fio->FilePath(), _T(".mtw"))) {
536 play_fio->Fread(header, sizeof(header), 1);
537 uint16_t size = header[0x12] | (header[0x13] << 8);
538 // load standard PCM wave file
539 if((buffer_length = load_wav_image(sizeof(header) + size)) != 0) {
540 play = is_wav = true;
542 } else if(check_file_extension(play_fio->FilePath(), _T(".p6"))) {
543 // NEC PC-6001/6601 series tape image
544 if((buffer_length = load_p6_image(false)) != 0) {
545 buffer = (uint8_t *)malloc(buffer_length);
546 load_p6_image(false);
547 play = is_wav = true;
549 } else if(check_file_extension(play_fio->FilePath(), _T(".p6t"))) {
550 // NEC PC-6001/6601 series tape image
551 if((buffer_length = load_p6_image(true)) != 0) {
552 buffer = (uint8_t *)malloc(buffer_length);
554 play = is_wav = true;
556 } else if(check_file_extension(play_fio->FilePath(), _T(".bin"))) {
557 // HITACH BASIC Master Jr tape image (bm2)
558 if((buffer_length = load_bmjr_image()) != 0) {
559 buffer = (uint8_t *)malloc(buffer_length);
561 play = is_wav = true;
563 } else if(check_file_extension(play_fio->FilePath(), _T(".cas"))) {
564 // standard cas image for my emulator
565 if((buffer_length = load_cas_image()) != 0) {
566 buffer = (uint8_t *)malloc(buffer_length);
568 play = is_wav = true;
574 if(!is_wav && buffer_length != 0) {
575 buffer_bak = (uint8_t *)malloc(buffer_length);
576 my_memcpy(buffer_bak, buffer, buffer_length);
579 // get the first signal
580 bool signal = ((buffer[0] & 0x80) != 0);
581 if(signal != in_signal) {
583 write_signals(&outputs_ear, signal ? 0xffffffff : 0);
588 apss_buffer_length = sample_rate * 2;
589 apss_buffer = (bool *)calloc(apss_buffer_length, 1);
590 apss_ptr = apss_count = 0;
591 apss_signals = false;
592 write_signals(&outputs_apss, 0);
599 bool DATAREC::rec_tape(const _TCHAR* file_path)
603 if(rec_fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
604 my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
606 sample_usec = 1000000. / sample_rate;
607 buffer_length = 1024 * 1024;
608 buffer = (uint8_t *)calloc(buffer_length, 1);
610 if(check_file_extension(file_path, _T(".wav"))) {
612 write_dummy_wav_header((void *)rec_fio);
614 } else if(check_file_extension(file_path, _T(".tap"))) {
616 rec_fio->FputUint32((uint32_t)sample_rate);
617 is_wav = is_tap = true;
618 } else if(check_file_extension(file_path, _T(".t77"))) {
621 sample_rate = (int)(1000000.0 / sample_usec + 0.5);
623 rec_fio->Fwrite((void *)("XM7 TAPE IMAGE 0"), 16, 1);
624 rec_fio->FputUint16(0); // marker
627 buffer[0] = out_signal ? 0x80 : 0;
631 buffer[0] = out_signal ? 0x80 : 0;
639 void DATAREC::close_tape()
643 if(register_id >= 0) {
644 cancel_event(this, register_id);
649 play = rec = is_wav = is_tap = is_t77 = false;
650 buffer_ptr = buffer_length = 0;
656 write_signals(&outputs_ear, 0);
660 void DATAREC::close_file()
662 if(play_fio->IsOpened()) {
665 if(rec_fio->IsOpened()) {
668 for(int i = 0; i < buffer_ptr; i += 8) {
670 for(int j = 0, bit = 0x80; j < 8; j++, bit >>= 1) {
671 if(i + j < buffer_ptr && buffer[i + j] >= 0x80) {
675 rec_fio->FputUint8(val);
678 rec_fio->Fwrite(buffer, buffer_ptr + 2, 1);
682 rec_fio->Fwrite(buffer, buffer_ptr + 1, 1);
692 if(buffer_bak != NULL) {
696 //#ifdef DATAREC_SOUND
697 if(__DATAREC_SOUND) {
698 if(sound_buffer != NULL) {
704 if(apss_buffer != NULL) {
710 // standard PCM wave file
712 void adjust_zero_position(int16_t *wav_buffer, int samples, int sample_rate)
714 int16_t *zero_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
715 int width = (int)((double)sample_rate / 1000.0 + 0.5);
717 for(int i = width; i < samples - width; i++) {
718 int max_sample = -65536, min_sample = 65536;
719 for(int j = -width; j < width; j++) {
720 if(max_sample < (int)wav_buffer[i + j]) max_sample = (int)wav_buffer[i + j];
721 if(min_sample > (int)wav_buffer[i + j]) min_sample = (int)wav_buffer[i + j];
723 if(max_sample - min_sample > 4096) {
724 zero_buffer[i] = (int16_t)((max_sample + min_sample) / 2);
726 zero_buffer[i] = wav_buffer[i];
729 for(int i = 0; i < samples; i++) {
730 wav_buffer[i] -= zero_buffer[(i < width) ? width : (i < samples - width) ? i : (samples - width - 1)];
734 int DATAREC::load_wav_image(int offset)
743 pair16_t __sample_bits;
745 pair32_t __sample_rate;
746 pair32_t __chunk_size;
748 play_fio->Fseek(offset, FILEIO_SEEK_SET);
749 play_fio->Fread(&header, sizeof(header), 1);
751 __fmt_id.set_2bytes_le_from(header.format_id);
752 __sample_bits.set_2bytes_le_from(header.sample_bits);
754 if((__fmt_id.u16 != 1) || !((__sample_bits.u16 == 8) || (__sample_bits.u16 == 16))) {
757 tmpval32.set_4bytes_le_from(header.fmt_chunk.size);
758 play_fio->Fseek(tmpval32.d - 16, FILEIO_SEEK_CUR);
760 play_fio->Fread(&chunk, sizeof(chunk), 1);
761 __chunk_size.set_4bytes_le_from(chunk.size);
762 if(strncmp(chunk.id, "data", 4) == 0) {
766 play_fio->Fseek(tmpval32.d, FILEIO_SEEK_CUR);
769 __channels.set_2bytes_le_from(header.channels);
771 int samples = (int)(__chunk_size.d / (uint32_t)(__channels.u16)), loaded_samples = 0;
773 if(__sample_bits.u16 == 16) {
776 __sample_rate.set_4bytes_le_from(header.sample_rate);
777 sample_rate = __sample_rate.d;
778 sample_usec = 1000000. / (float)sample_rate;
782 #define TMP_LENGTH (0x10000 * (uint32_t)(__channels.u16))
784 uint8_t *tmp_buffer = (uint8_t *)malloc(TMP_LENGTH);
785 play_fio->Fread(tmp_buffer, TMP_LENGTH, 1);
787 #define GET_SAMPLE { \
788 for(int ch = 0; ch < __channels.s16; ch++) { \
789 if(__sample_bits.u16 == 16) { \
796 pair.b.l = tmp_buffer[tmp_ptr++]; \
797 pair.b.h = tmp_buffer[tmp_ptr++]; \
798 sample[ch] = pair.s16; \
800 sample[ch] = (tmp_buffer[tmp_ptr++] - 128) * 256; \
803 if(tmp_ptr == TMP_LENGTH) { \
804 play_fio->Fread(tmp_buffer, TMP_LENGTH, 1); \
810 if(__DATAREC_SOUND) {
811 if(!config.wave_shaper[drive_num] || __channels.u16 > 1) {
815 if(!config.wave_shaper[drive_num]) {
819 //#ifdef DATAREC_SOUND
820 // if(!config.wave_shaper[drive_num] || header.channels > 1) {
822 // if(!config.wave_shaper[drive_num]) {
826 //#ifdef DATAREC_SOUND
827 if(__DATAREC_SOUND) {
828 if(__channels.u16 > 1) {
829 sound_buffer_length = samples * sizeof(int16_t);
830 sound_buffer = (int16_t *)malloc(sound_buffer_length);
834 int16_t *wav_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
835 for(int i = 0, tmp_ptr = 0; i < samples; i++) {
838 int16_t sample_signal = sample[0];
839 //#ifdef DATAREC_SOUND
840 if(__DATAREC_SOUND) {
841 if(__channels.u16 > 1) {
842 //#ifdef DATAREC_SOUND_LEFT
843 if(__DATAREC_SOUND_LEFT) {
844 sample_signal = sample[1];
845 sound_buffer[i] = sample[0];
848 sound_buffer[i] = sample[1];
854 wav_buffer[i] = sample_signal;
856 adjust_zero_position(wav_buffer, samples, __sample_rate.d);
858 // copy to dest buffer
859 buffer = (uint8_t *)malloc(samples);
860 bool prev_signal = false;
862 int16_t max_sample = 0, min_sample = 0;
864 for(int i = 0 /*, tmp_ptr = 0 */; i < samples; i++) {
865 int16_t sample_signal = wav_buffer[i];
866 bool signal = (sample_signal > 0);
868 if(!prev_signal && signal) {
869 if(!(min_sample < -2048)) {
870 for(int j = top_index; j < i; j++) {
874 } else if(prev_signal && !signal) {
875 if(!(max_sample > 2048)) {
876 for(int j = top_index; j < i; j++) {
881 if(prev_signal != signal) {
883 max_sample = min_sample = 0;
886 if(max_sample < sample_signal) {
887 max_sample = sample_signal;
890 if(min_sample > sample_signal) {
891 min_sample = sample_signal;
894 buffer[i] = (signal ? 0xff : 0);
895 prev_signal = signal;
898 if(!(min_sample < -2048)) {
899 for(int j = top_index; j < samples; j++) {
904 if(!(max_sample > 2048)) {
905 for(int j = top_index; j < samples; j++) {
912 loaded_samples = samples;
915 int16_t *wav_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
916 for(int i = 0, tmp_ptr = 0; i < samples; i++) {
919 wav_buffer[i] = sample[0];
921 adjust_zero_position(wav_buffer, samples, __sample_rate.d);
923 // t=0 : get thresholds
924 // t=1 : get number of samples
925 // t=2 : load samples
926 #define FREQ_SCALE 16
927 int min_threshold = (int)(__sample_rate.d * FREQ_SCALE / 2400.0 / 2.0 / 3.0 + 0.5);
928 int max_threshold = (int)(__sample_rate.d * FREQ_SCALE / 1200.0 / 2.0 * 3.0 + 0.5);
929 int half_threshold, hi_count, lo_count;
930 int *counts = (int *)calloc(max_threshold, sizeof(int));
932 for(int t = 0; t < 3; t++) {
933 int count_positive = 0, count_negative = 0;
934 bool prev_signal = false;
936 for(int i = 0; i < samples - 1; i++) {
937 int prev = wav_buffer[i], next = wav_buffer[i + 1];
938 double diff = (double)(next - prev) / FREQ_SCALE;
939 for(int j = 0; j < FREQ_SCALE; j++) {
940 int sample = prev + (int)(diff * j + 0.5);
941 bool signal = (sample > 0);
943 if(!prev_signal && signal) {
945 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
946 counts[count_positive]++;
949 int count_p = count_positive / FREQ_SCALE;
950 int count_n = count_negative / FREQ_SCALE;
951 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
952 count_p = (count_positive > half_threshold) ? hi_count : lo_count;
953 if(count_negative < max_threshold) {
958 for(int j = 0; j < count_p; j++) buffer[loaded_samples++] = 0xff;
959 for(int j = 0; j < count_n; j++) buffer[loaded_samples++] = 0x00;
961 loaded_samples += count_p + count_n;
964 count_positive = count_negative = 0;
971 prev_signal = signal;
975 long sum_value = 0, sum_count = 0, half_tmp;
976 for(int i = 0; i < max_threshold; i++) {
977 sum_value += i * counts[i];
978 sum_count += counts[i];
980 // 1920 = 2400 * 0.6 + 1200 * 0.4
981 if(sum_count > 60 * 1920) {
982 half_tmp = (int)((double)sum_value / (double)sum_count + 0.5);
984 half_tmp = (int)(__sample_rate.d * FREQ_SCALE / 1920.0 / 2.0 + 0.5);
987 sum_value = sum_count = 0;
988 for(int i = 0; i < half_tmp; i++) {
989 sum_value += i * counts[i];
990 sum_count += counts[i];
992 double lo_tmp = (double)sum_value / (double)sum_count;
994 sum_value = sum_count = 0;
995 for(int i = half_tmp; i < half_tmp * 2; i++) {
996 sum_value += i * counts[i];
997 sum_count += counts[i];
999 double hi_tmp = (double)sum_value / (double)sum_count;
1001 half_threshold = (int)((lo_tmp + hi_tmp) / 2 + 0.5);
1002 min_threshold = (int)(2 * lo_tmp - half_threshold + 0.5);
1003 max_threshold = (int)(2 * hi_tmp - half_threshold + 0.5);
1004 lo_count = (int)(lo_tmp / FREQ_SCALE + 0.5);
1005 hi_count = (int)(hi_tmp / FREQ_SCALE + 0.5);
1007 int count_p = count_positive / FREQ_SCALE;
1008 int count_n = count_negative / FREQ_SCALE;
1009 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
1010 count_p = (count_positive > half_threshold) ? hi_count : lo_count;
1011 if(count_negative < max_threshold) {
1015 if(buffer != NULL) {
1016 for(int j = 0; j < count_p; j++) buffer[loaded_samples++] = 0xff;
1017 for(int j = 0; j < count_n; j++) buffer[loaded_samples++] = 0x00;
1019 loaded_samples += count_p + count_n;
1023 buffer = (uint8_t *)malloc(loaded_samples);
1024 //#ifdef DATAREC_SOUND
1025 if(__DATAREC_SOUND) {
1026 if(__channels.u16 > 1) {
1027 sound_buffer_length = loaded_samples * sizeof(int16_t);
1028 sound_buffer = (int16_t *)malloc(sound_buffer_length);
1040 return loaded_samples;
1044 void DATAREC::save_wav_image()
1046 // write samples remained in buffer
1047 if(buffer_ptr > 0) {
1048 rec_fio->Fwrite(buffer, buffer_ptr, 1);
1051 uint32_t length = rec_fio->Ftell();
1053 wav_header_t wav_header;
1054 wav_chunk_t wav_chunk;
1056 pair32_t __riff_chunk_size;
1057 pair32_t __fmt_chunk_size;
1058 pair32_t __wav_chunk_size;
1060 pair16_t __channels;
1061 pair32_t __sample_rate;
1062 pair16_t __block_size;
1063 pair16_t __sample_bits;
1065 __riff_chunk_size.d = length - 8;
1066 __fmt_chunk_size.d = 16;
1069 __sample_rate.d = sample_rate;
1070 __block_size.u16 = 1;
1071 __sample_bits.u16 = 8;
1072 memcpy(wav_header.riff_chunk.id, "RIFF", 4);
1073 wav_header.riff_chunk.size = __riff_chunk_size.get_4bytes_le_to();
1075 memcpy(wav_header.wave, "WAVE", 4);
1076 memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
1077 wav_header.fmt_chunk.size = __riff_chunk_size.get_4bytes_le_to();
1078 wav_header.format_id = __fmt_id.get_2bytes_le_to();
1079 wav_header.channels = __channels.get_2bytes_le_to();
1080 wav_header.sample_rate = __sample_rate.get_4bytes_le_to();
1081 wav_header.data_speed = __sample_rate.get_4bytes_le_to();
1082 wav_header.block_size = __block_size.get_2bytes_le_to();
1083 wav_header.sample_bits = __sample_bits.get_2bytes_le_to();
1085 memcpy(wav_chunk.id, "data", 4);
1086 __wav_chunk_size.d = length - sizeof(wav_header) - sizeof(wav_chunk);
1087 wav_chunk.size = __wav_chunk_size.get_4bytes_le_to();
1089 rec_fio->Fseek(0, FILEIO_SEEK_SET);
1090 rec_fio->Fwrite(&wav_header, sizeof(wav_header), 1);
1091 rec_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
1093 if(set_wav_header(&wav_header, &wav_chunk, 1, sample_rate, 8, length)) {
1094 rec_fio->Fseek(0, FILEIO_SEEK_SET);
1095 rec_fio->Fwrite(&wav_header, sizeof(wav_header), 1);
1096 rec_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
1101 // FUJITSU FM-7 series tape image
1103 #define T77_PUT_SIGNAL(signal, len) { \
1105 while(remain > 0) { \
1106 if(buffer != NULL) { \
1107 buffer[ptr++] = (signal) ? 0xff : 0x00; \
1115 int DATAREC::load_t77_image()
1118 sample_rate = (int)(1000000.0 / sample_usec + 0.5);
1123 int file_size = (int)play_fio->FileLength();
1125 if(file_size <= 0) {
1126 return 0; // over 2GB
1128 play_fio->Fseek(0, FILEIO_SEEK_SET);
1129 play_fio->Fread(tmpbuf, 16, 1);
1131 if(strcmp((char *)tmpbuf, "XM7 TAPE IMAGE 0") != 0) {
1136 while(file_size > 0) {
1137 uint16_t h = play_fio->FgetUint8();
1138 uint16_t l = play_fio->FgetUint8();
1139 uint16_t v = h * 256 + l;
1141 if((file_size -= 2) < 0) {
1145 T77_PUT_SIGNAL((h & 0x80) != 0, v & 0x7fff);
1151 // SHARP X1 series tape image
1154 new tape file format for t-tune (from tape_fmt.txt)
1157 00H : 4 :
\8e¯
\95Ê
\83C
\83\93\83f
\83b
\83N
\83X "TAPE"
1158 04H : 17 :
\83e
\81[
\83v
\82Ì
\96¼
\91O(asciiz)
1159 15H : 5 :
\83\8a\83U
\81[
\83u
1160 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
1161 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
1162 1CH : 4 :
\83T
\83\93\83v
\83\8a\83\93\83O
\8eü
\94g
\90\94(
\82g
\82\9a\92P
\88Ê
\81j
1163 20H : 4 :
\83e
\81[
\83v
\83f
\81[
\83^
\82Ì
\83T
\83C
\83Y
\81i
\83r
\83b
\83g
\92P
\88Ê
\81j
1164 24H : 4 :
\83e
\81[
\83v
\82Ì
\88Ê
\92u
\81i
\83r
\83b
\83g
\92P
\88Ê
\81j
1165 28H : ? :
\83e
\81[
\83v
\82Ì
\83f
\81[
\83^
1168 int DATAREC::load_tap_image()
1171 play_fio->Fseek(0, FILEIO_SEEK_END);
1172 //int file_size = play_fio->Ftell();
1173 play_fio->Fseek(0, FILEIO_SEEK_SET);
1177 play_fio->Fread(header, 4, 1);
1179 if(header[0] == 'T' && header[1] == 'A' && header[2] == 'P' && header[3] == 'E') {
1180 // skip name, reserved, write protect notch
1181 play_fio->Fseek(17 + 5 + 1, FILEIO_SEEK_CUR);
1183 if(play_fio->Fgetc() != 0x01) {
1184 // unknown data format
1188 play_fio->Fread(header, 4, 1);
1189 sample_rate = header[0] | (header[1] << 8) | (header[2] << 16) | (header[3] << 24);
1190 sample_usec = 1000000. / sample_rate;
1192 play_fio->Fread(header, 4, 1);
1194 play_fio->Fread(header, 4, 1);
1197 sample_rate = header[0] | (header[1] << 8) | (header[2] << 16) | (header[3] << 24);
1198 sample_usec = 1000000. / sample_rate;
1203 while((data = play_fio->Fgetc()) != EOF) {
1204 for(int i = 0, bit = 0x80; i < 8; i++, bit >>= 1) {
1205 if(buffer != NULL) {
1206 buffer[ptr] = ((data & bit) != 0) ? 255 : 0;
1214 // SHARP MZ series tape image
1216 //#define MZT_PUT_SIGNAL(signal, len) { \
1217 // int remain = len; \
1218 // while(remain > 0) { \
1219 // if(buffer != NULL) { \
1220 // buffer[ptr++] = ((signal != 0) ? 0x80 : 0) | min(remain, 0x7f); \
1224 // remain -= min(remain, 0x7f); \
1228 #define MZT_PUT_SIGNAL(signal, len) { \
1230 while(remain > 0) { \
1231 if(buffer != NULL) { \
1232 buffer[ptr++] = (signal != 0) ? 0xff : 0; \
1240 #define MZT_PUT_BIT(bit, len) { \
1241 for(int l = 0; l < (len); l++) { \
1243 MZT_PUT_SIGNAL(1, len1); \
1244 MZT_PUT_SIGNAL(0, len2); \
1246 MZT_PUT_SIGNAL(1, len3); \
1247 MZT_PUT_SIGNAL(0, len4); \
1252 #define MZT_PUT_BYTE(byte) { \
1253 MZT_PUT_BIT(1, 1); \
1254 for(int j = 0; j < 8; j++) { \
1255 if((byte) & (0x80 >> j)) { \
1256 MZT_PUT_BIT(1, 1); \
1259 MZT_PUT_BIT(0, 1); \
1264 #define MZT_PUT_BLOCK(buf, len) { \
1266 for(int i = 0; i < (len); i++) { \
1267 MZT_PUT_BYTE((buf)[i]); \
1269 uint8_t hi = (count >> 8) & 0xff; \
1270 uint8_t lo = (count >> 0) & 0xff; \
1275 int DATAREC::load_mzt_image()
1277 int len1, len2, len3, len4;
1278 sample_rate = 48000;
1279 sample_usec = 1000000. / sample_rate;
1281 len1 = len2 = (int)(120.0 / 16.0 * sample_rate / 22050.0 + 0.5);
1282 len3 = len4 = (int)(60.0 / 16.0 * sample_rate / 22050.0 + 0.5);
1284 len1 = (int)(24.0 * sample_rate / 48000.0 + 0.5);
1285 len2 = (int)(29.0 * sample_rate / 48000.0 + 0.5);
1286 len3 = (int)(11.0 * sample_rate / 48000.0 + 0.5);
1287 len4 = (int)(15.0 * sample_rate / 48000.0 + 0.5);
1292 play_fio->Fseek(0, FILEIO_SEEK_END);
1293 int file_size = play_fio->Ftell();
1294 play_fio->Fseek(0, FILEIO_SEEK_SET);
1298 while(file_size > 128) {
1300 uint8_t header[128], ram[0x20000];
1301 play_fio->Fread(header, sizeof(header), 1);
1302 file_size -= sizeof(header);
1304 uint16_t size = header[0x12] | (header[0x13] << 8);
1305 uint16_t offs = header[0x14] | (header[0x15] << 8);
1306 memset(ram, 0, sizeof(ram));
1307 play_fio->Fread(ram + offs, size, 1);
1309 //#if defined(_MZ80K) || defined(_MZ700) || defined(_MZ1200) || defined(_MZ1500)
1311 // apply mz700win patch
1312 if(header[0x40] == 'P' && header[0x41] == 'A' && header[0x42] == 'T' && header[0x43] == ':') {
1313 int patch_ofs = 0x44;
1314 for(; patch_ofs < 0x80; ) {
1315 uint16_t patch_addr = header[patch_ofs] | (header[patch_ofs + 1] << 8);
1317 if(patch_addr == 0xffff) {
1320 int patch_len = header[patch_ofs++];
1321 for(int i = 0; i < patch_len; i++) {
1322 ram[patch_addr + i] = header[patch_ofs++];
1325 for(int i = 0x40; i < patch_ofs; i++) {
1331 MZT_PUT_SIGNAL(0, sample_rate);
1332 //#if defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200)
1335 MZT_PUT_BIT(0, 22000);
1338 MZT_PUT_BLOCK(header, 128);
1340 MZT_PUT_SIGNAL(1, (int)(22.0 * sample_rate / 22050.0 + 0.5));
1341 MZT_PUT_SIGNAL(0, (int)(22.0 * sample_rate / 22050.0 + 0.5));
1342 MZT_PUT_SIGNAL(0, sample_rate);
1343 MZT_PUT_BIT(0, 11000);
1346 MZT_PUT_BLOCK(ram + offs, size);
1350 // format info written in
\8e\8e\8c±
\82É
\8fo
\82éX1
1351 MZT_PUT_BIT(0, 10000);
1355 MZT_PUT_BLOCK(header, 128);
1357 MZT_PUT_BIT(0, 256);
1358 MZT_PUT_BLOCK(header, 128);
1360 MZT_PUT_SIGNAL(0, sample_rate);
1361 MZT_PUT_BIT(0, 10000);
1365 MZT_PUT_BLOCK(ram + offs, size);
1373 // NEC PC-6001/6601 series tape image
1375 #define P6_PUT_1200HZ() { \
1376 if(buffer != NULL) { \
1377 for(int p = 0; p < 20; p++) buffer[ptr++] = 0xff; \
1378 for(int p = 0; p < 20; p++) buffer[ptr++] = 0x00; \
1384 #define P6_PUT_2400HZ() { \
1385 if(buffer != NULL) { \
1386 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1387 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1393 #define P6_PUT_2400HZ_X2() { \
1394 if(buffer != NULL) { \
1395 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1396 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1397 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1398 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1404 int DATAREC::load_p6_image(bool is_p6t)
1406 sample_rate = 48000;
1407 sample_usec = 1000000. / sample_rate;
1409 int ptr = 0, remain = 0x10000, data;
1411 // get info block offset
1412 play_fio->Fseek(-4, FILEIO_SEEK_END);
1413 int length = play_fio->FgetInt32();
1415 play_fio->Fseek(length, FILEIO_SEEK_SET);
1416 char id_p = play_fio->Fgetc();
1417 char id_6 = play_fio->Fgetc();
1418 uint8_t ver = play_fio->FgetUint8();
1419 if(id_p == 'P' && id_6 == '6' && ver == 2) {
1420 uint8_t blocks = play_fio->FgetUint8();
1422 play_fio->FgetUint8();
1423 play_fio->FgetUint8();
1424 play_fio->FgetUint8();
1425 uint16_t cmd = play_fio->FgetUint16();
1426 play_fio->Fseek(cmd, FILEIO_SEEK_CUR);
1427 uint16_t exp = play_fio->FgetUint16();
1428 play_fio->Fseek(exp, FILEIO_SEEK_CUR);
1429 // check 1st data block
1430 char id_t = play_fio->Fgetc();
1431 char id_i = play_fio->Fgetc();
1432 if(id_t == 'T' && id_i == 'I') {
1433 play_fio->FgetUint8();
1434 play_fio->Fseek(16, FILEIO_SEEK_CUR);
1435 uint16_t baud = play_fio->FgetUint16(); // 600 or 1200
1436 sample_rate = sample_rate * baud / 1200;
1437 sample_usec = 1000000. / sample_rate;
1440 remain = min(length, 0x10000);
1443 play_fio->Fseek(0, FILEIO_SEEK_SET);
1445 for(int i = 0; i < 9600; i++) {
1448 for(int i = 0; i < 16; i++) {
1449 data = play_fio->Fgetc();
1451 for(int j = 0; j < 8; j++) {
1452 if(data & (1 << j)) {
1463 // for(int i = 0; i < 1280; i++) {
1464 for(int i = 0; i < 2400; i++) {
1467 while((data = play_fio->Fgetc()) != EOF && remain > 0) {
1469 for(int j = 0; j < 8; j++) {
1470 if(data & (1 << j)) {
1482 for(int i = 0; i < 16; i++) {
1484 for(int j = 0; j < 8; j++) {
1495 // HITACH BASIC Master Jr tape image (bm2)
1497 #define BMJR_PUT_1200HZ_X4() { \
1498 if(buffer != NULL) { \
1499 for(int k = 0; k < 4; k++) { \
1500 for(int p = 0; p < 20; p++) buffer[ptr++] = 0xff; \
1501 for(int p = 0; p < 20; p++) buffer[ptr++] = 0x00; \
1508 #define BMJR_PUT_2400HZ_X8() { \
1509 if(buffer != NULL) { \
1510 for(int k = 0; k < 8; k++) { \
1511 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1512 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1519 int DATAREC::load_bmjr_image()
1521 sample_rate = 48000;
1522 sample_usec = 1000000. / sample_rate;
1524 play_fio->Fseek(0, FILEIO_SEEK_SET);
1527 while((data = play_fio->Fgetc()) != EOF) {
1529 BMJR_PUT_1200HZ_X4();
1531 for(int j = 0; j < 8; j++) {
1532 if(data & (1 << j)) {
1533 BMJR_PUT_2400HZ_X8();
1535 BMJR_PUT_1200HZ_X4();
1539 BMJR_PUT_2400HZ_X8();
1540 BMJR_PUT_2400HZ_X8();
1545 // standard cas image for my emulator
1547 static const uint8_t msx_cas_header[8] = {0x1f, 0xa6, 0xde, 0xba, 0xcc, 0x13, 0x7d, 0x74};
1549 int DATAREC::load_cas_image()
1551 sample_rate = 48000;
1552 sample_usec = 1000000. / sample_rate;
1554 // SORD m5 or NEC PC-6001 series cas image ?
1555 static const uint8_t momomomomomo[6] = {0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3};
1556 uint8_t tmp_header[8];
1557 play_fio->Fseek(0, FILEIO_SEEK_SET);
1558 play_fio->Fread(tmp_header, sizeof(tmp_header), 1);
1560 if(memcmp(tmp_header, "SORDM5", 6) == 0) {
1561 return load_m5_cas_image();
1562 } else if(memcmp(tmp_header, msx_cas_header, 8) == 0) {
1563 return load_msx_cas_image();
1564 } else if(memcmp(tmp_header, momomomomomo, 6) == 0) {
1565 return load_p6_image(false);
1568 // this is the standard cas image for my emulator
1569 play_fio->Fseek(0, FILEIO_SEEK_SET);
1571 while((data = play_fio->Fgetc()) != EOF) {
1572 for(int i = 0; i < (data & 0x7f); i++) {
1573 if(buffer != NULL) {
1574 buffer[ptr] = (data & 0x80) ? 255 : 0;
1582 // SORD M5 tape image
1584 #define M5_PUT_BIT(val, len) { \
1586 while(remain > 0) { \
1587 if(buffer != NULL) { \
1588 buffer[ptr] = val ? 0 : 0xff; \
1595 #define M5_PUT_BYTE(data) { \
1596 for(int j = 0; j < 10; j++) { \
1597 int bit = (j == 0) ? 1 : (j == 1) ? 0 : ((data >> (j - 2)) & 1); \
1599 M5_PUT_BIT(0xff, 8); \
1600 M5_PUT_BIT(0x00, 7); \
1602 M5_PUT_BIT(0xff, 16); \
1603 M5_PUT_BIT(0x00, 14); \
1608 int DATAREC::load_m5_cas_image()
1610 play_fio->Fseek(16, FILEIO_SEEK_SET);
1611 int ptr = 0, block_type;
1613 while((block_type = play_fio->Fgetc()) != EOF) {
1614 if(block_type != 'H' && block_type != 'D') {
1617 int block_size = play_fio->Fgetc();
1619 if(block_type == 'H') {
1620 M5_PUT_BIT(0x00, 1);
1622 for(int i = 0; i < (block_type == 'H' ? 945 : 59); i++) {
1623 M5_PUT_BIT(0xff, 8);
1624 M5_PUT_BIT(0x00, 7);
1626 M5_PUT_BYTE(block_type);
1627 M5_PUT_BYTE(block_size);
1629 for(int i = 0; i < ((block_size == 0) ? 0x101 : (block_size + 1)); i++) {
1630 uint8_t data = play_fio->Fgetc();
1633 M5_PUT_BIT(0xff, 8);
1634 M5_PUT_BIT(0x00, 7);
1636 M5_PUT_BIT(0x00, 1);
1640 // ASCII MSX tape image (fMSX)
1641 // MAME/MESS /src/lib/formats/fmsx_cas.c by Mr.Sean Young
1643 #define CAS_PERIOD (16)
1644 #define CAS_HEADER_PERIODS (4000)
1645 #define CAS_EMPTY_PERIODS (1000)
1647 int DATAREC::load_msx_cas_image()
1649 sample_rate = 22050;
1650 sample_usec = 1000000. / sample_rate;
1652 play_fio->Fseek(0, FILEIO_SEEK_END);
1653 int cas_size = play_fio->Ftell();
1654 uint8_t *bytes = (uint8_t *)malloc(cas_size);
1655 play_fio->Fseek(0, FILEIO_SEEK_SET);
1656 play_fio->Fread(bytes, cas_size, 1);
1658 int cas_pos, bit, state = 1, samples_pos, size, n, i, p;
1663 while(/*samples_pos < sample_count && */cas_pos < cas_size) {
1664 /* Check if we need to output a header */
1665 if(cas_pos + 8 < cas_size) {
1666 if(!memcmp( bytes + cas_pos, msx_cas_header, 8)) {
1667 /* Write CAS_EMPTY_PERIODS of silence */
1668 n = CAS_EMPTY_PERIODS * CAS_PERIOD;
1670 if(buffer != NULL) {
1671 buffer[samples_pos] = 0;
1675 /* Write CAS_HEADER_PERIODS of header (high frequency) */
1676 for(i = 0; i < CAS_HEADER_PERIODS * 4 ; i++) {
1677 for(n = 0; n < CAS_PERIOD / 4; n++) {
1678 if(buffer != NULL) {
1679 buffer[samples_pos + n] = (state ? 0xff : 0);
1682 samples_pos += CAS_PERIOD / 4 ;
1689 for(i = 0; i <= 11; i++) {
1693 bit = (bytes[cas_pos] & (1 << (i - 1) ) );
1698 /* write this one bit */
1699 for(n = 0; n < (bit ? 4 : 2); n++) {
1700 size = (bit ? CAS_PERIOD / 4 : CAS_PERIOD / 2);
1701 for(p = 0; p < size; p++) {
1702 if(buffer != NULL) {
1703 buffer[samples_pos + p] = (state ? 0xff : 0);
1707 samples_pos += size;
1716 void DATAREC::mix(int32_t* buffer, int cnt)
1718 int32_t* buffer_tmp = buffer;
1720 if(config.sound_play_tape && pcm_changed && remote && (play || rec) && ff_rew == 0) {
1721 bool signal = ((play && in_signal) || (rec && out_signal));
1723 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
1725 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
1727 int clocks = pcm_positive_clocks + pcm_negative_clocks;
1728 int sample = clocks ? (pcm_max_vol * pcm_positive_clocks - pcm_max_vol * pcm_negative_clocks) / clocks : signal ? pcm_max_vol : -pcm_max_vol;
1730 pcm_last_vol_l = apply_volume(sample, pcm_volume_l);
1731 pcm_last_vol_r = apply_volume(sample, pcm_volume_r);
1733 for(int i = 0; i < cnt; i++) {
1734 *buffer++ += pcm_last_vol_l; // L
1735 *buffer++ += pcm_last_vol_r; // R
1737 } else if(pcm_last_vol_l || pcm_last_vol_r) {
1738 // suppress petite noise when go to mute
1739 for(int i = 0; i < cnt; i++) {
1740 *buffer++ += pcm_last_vol_l; // L
1741 *buffer++ += pcm_last_vol_r; // R
1743 if(pcm_last_vol_l > 0) {
1745 } else if(pcm_last_vol_l < 0) {
1748 if(pcm_last_vol_r > 0) {
1750 } else if(pcm_last_vol_r < 0) {
1755 pcm_prev_clock = get_current_clock();
1756 pcm_positive_clocks = pcm_negative_clocks = 0;
1758 //#ifdef DATAREC_SOUND
1759 if(__DATAREC_SOUND) {
1760 if(/*config.sound_play_tape && */remote && play && ff_rew == 0) {
1761 sound_last_vol_l = apply_volume(sound_sample, sound_volume_l);
1762 sound_last_vol_r = apply_volume(sound_sample, sound_volume_r);
1763 buffer = buffer_tmp; // restore
1764 for(int i = 0; i < cnt; i++) {
1765 *buffer += sound_last_vol_l; // L
1766 *buffer += sound_last_vol_r; // R
1768 } else if(sound_last_vol_l || sound_last_vol_r) {
1769 // suppress petite noise when go to mute
1770 for(int i = 0; i < cnt; i++) {
1771 *buffer++ += sound_last_vol_l; // L
1772 *buffer++ += sound_last_vol_r; // R
1774 if(sound_last_vol_l > 0) {
1776 } else if(sound_last_vol_l < 0) {
1779 if(sound_last_vol_r > 0) {
1781 } else if(sound_last_vol_r < 0) {
1790 void DATAREC::set_volume(int ch, int decibel_l, int decibel_r)
1793 pcm_volume_l = decibel_to_volume(decibel_l);
1794 pcm_volume_r = decibel_to_volume(decibel_r);
1795 //#ifdef DATAREC_SOUND
1796 } else if(ch == 1) {
1797 if(__DATAREC_SOUND) {
1798 sound_volume_l = decibel_to_volume(decibel_l);
1799 sound_volume_r = decibel_to_volume(decibel_r);
1805 double DATAREC::get_ave_hi_freq()
1807 if(ave_hi_freq == 0 && play && is_wav) {
1808 bool prev_signal = false;
1809 int positive = 0, negative = 0, pulse_count = 0;
1811 double base_usec = 1000000.0 / (double)sample_rate;
1813 for(int i=0; i < buffer_length; i++) {
1814 bool next_signal = ((buffer[i] & 0x80) != 0);
1815 if(!prev_signal && next_signal) {
1816 double usec = base_usec * (positive + negative);
1817 if(316.667 <= usec && usec < 516.667) {
1820 } else if(633.333 <= usec && usec < 1033.333) {
1824 positive = negative = 0;
1831 prev_signal = next_signal;
1833 if(sum != 0 && pulse_count != 0) {
1834 double average = sum / pulse_count;
1835 ave_hi_freq = 1000000.0 / average;
1838 if(ave_hi_freq == 0) {
1844 void DATAREC::update_config()
1846 if(d_noise_play != NULL) {
1847 d_noise_play->set_mute(!config.sound_noise_cmt);
1849 if(d_noise_stop != NULL) {
1850 d_noise_stop->set_mute(!config.sound_noise_cmt);
1852 if(d_noise_fast != NULL) {
1853 d_noise_fast->set_mute(!config.sound_noise_cmt);
1855 update_realtime_render();
1858 #define STATE_VERSION 12
1860 bool DATAREC::process_state(FILEIO* state_fio, bool loading)
1864 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1867 if(!state_fio->StateCheckInt32(this_device_id)) {
1874 state_fio->StateValue(play);
1875 state_fio->StateValue(rec);
1876 state_fio->StateValue(remote);
1877 state_fio->StateValue(trigger);
1878 state_fio->StateArray(rec_file_path, sizeof(rec_file_path), 1);
1880 length_tmp = state_fio->FgetInt32_LE();
1882 rec_fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
1883 while(length_tmp != 0) {
1884 uint8_t buffer_tmp[1024];
1885 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
1886 state_fio->Fread(buffer_tmp, length_rw, 1);
1887 if(rec_fio->IsOpened()) {
1888 rec_fio->Fwrite(buffer_tmp, length_rw, 1);
1890 length_tmp -= length_rw;
1894 if(rec && rec_fio->IsOpened()) {
1895 length_tmp = (int)rec_fio->Ftell();
1896 rec_fio->Fseek(0, FILEIO_SEEK_SET);
1897 state_fio->FputInt32_LE(length_tmp);
1898 while(length_tmp != 0) {
1899 uint8_t buffer_tmp[1024];
1900 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
1901 rec_fio->Fread(buffer_tmp, length_rw, 1);
1902 state_fio->Fwrite(buffer_tmp, length_rw, 1);
1903 length_tmp -= length_rw;
1906 state_fio->FputInt32_LE(0);
1909 state_fio->StateInt32(ff_rew);
1910 state_fio->StateBool(in_signal);
1911 state_fio->StateBool(out_signal);
1912 state_fio->StateUint32(prev_clock);
1913 state_fio->StateInt32(positive_clocks);
1914 state_fio->StateInt32(negative_clocks);
1915 state_fio->StateInt32(signal_changed);
1916 state_fio->StateInt32(register_id);
1917 state_fio->StateBool(realtime);
1918 state_fio->StateInt32(sample_rate);
1919 state_fio->StateDouble(sample_usec);
1920 state_fio->StateInt32(buffer_ptr);
1922 if((buffer_length = state_fio->FgetInt32_LE()) != 0) {
1923 buffer = (uint8_t *)malloc(buffer_length);
1924 state_fio->Fread(buffer, buffer_length, 1);
1926 if((length_tmp = state_fio->FgetInt32_LE()) != 0) {
1927 buffer_bak = (uint8_t *)malloc(length_tmp);
1928 state_fio->Fread(buffer_bak, length_tmp, 1);
1930 if(__DATAREC_SOUND) {
1931 if((sound_buffer_length = state_fio->FgetInt32_LE()) != 0) {
1932 sound_buffer = (int16_t *)malloc(sound_buffer_length);
1933 state_fio->Fread(sound_buffer, sound_buffer_length, 1);
1938 state_fio->FputInt32_LE(buffer_length);
1939 state_fio->Fwrite(buffer, buffer_length, 1);
1941 state_fio->FputInt32_LE(0);
1944 state_fio->FputInt32_LE(buffer_length);
1945 state_fio->Fwrite(buffer_bak, buffer_length, 1);
1947 state_fio->FputInt32_LE(0);
1949 if(__DATAREC_SOUND) {
1951 state_fio->FputInt32_LE(sound_buffer_length);
1952 state_fio->Fwrite(sound_buffer, sound_buffer_length, 1);
1954 state_fio->FputInt32_LE(0);
1958 if(__DATAREC_SOUND) {
1959 state_fio->StateInt16(sound_sample);
1961 state_fio->StateBool(is_wav);
1962 state_fio->StateBool(is_tap);
1963 state_fio->StateBool(is_t77);
1965 if((apss_buffer_length = state_fio->FgetInt32_LE()) != 0) {
1966 apss_buffer = (bool *)malloc(apss_buffer_length);
1967 state_fio->Fread(apss_buffer, apss_buffer_length, 1);
1971 state_fio->FputInt32_LE(apss_buffer_length);
1972 state_fio->Fwrite(apss_buffer, apss_buffer_length, 1);
1974 state_fio->FputInt32_LE(0);
1977 state_fio->StateInt32(apss_ptr);
1978 state_fio->StateInt32(apss_count);
1979 state_fio->StateInt32(apss_remain);
1980 state_fio->StateBool(apss_signals);
1981 state_fio->StateInt32(pcm_changed);
1982 state_fio->StateUint32(pcm_prev_clock);
1983 state_fio->StateInt32(pcm_positive_clocks);
1984 state_fio->StateInt32(pcm_negative_clocks);
1988 pcm_last_vol_l = pcm_last_vol_r = 0;
1989 if(__DATAREC_SOUND) {
1990 sound_last_vol_l = sound_last_vol_r = 0;