OSDN Git Service

[VM] Add PC-8001/mk2/8801/mk2.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pcm1bit.cpp
index 8cf6833..645aa34 100644 (file)
 */
 
 #include "pcm1bit.h"
-#include "../fileio.h"
 
 void PCM1BIT::initialize()
 {
+       DEVICE::initialize();
        signal = false;
        on = true;
        mute = false;
-       
-#ifdef PCM1BIT_HIGH_QUALITY
-       sample_count = 0;
-       prev_clock = 0;
-       prev_vol = 0;
-#endif
-       update = 0;
+       realtime = false;
+       changed = 0;
+       last_vol_l = last_vol_r = 0;
        
        register_frame_event(this);
 }
 
-void PCM1BIT::write_signal(int id, uint32 data, uint32 mask)
+void PCM1BIT::reset()
+{
+       prev_clock = get_current_clock();
+       positive_clocks = negative_clocks = 0;
+}
+
+void PCM1BIT::write_signal(int id, uint32_t data, uint32_t mask)
 {
        if(id == SIG_PCM1BIT_SIGNAL) {
                bool next = ((data & mask) != 0);
                if(signal != next) {
-#ifdef PCM1BIT_HIGH_QUALITY
-                       if(sample_count < 1024) {
-                               samples_signal[sample_count] = signal;
-                               samples_out[sample_count] = (on && !mute);
-                               samples_clock[sample_count] = passed_clock(prev_clock);
-                               sample_count++;
+                       touch_sound();
+                       if(signal) {
+                               positive_clocks += get_passed_clock(prev_clock);
+                       } else {
+                               negative_clocks += get_passed_clock(prev_clock);
                        }
-#endif
+                       prev_clock = get_current_clock();
                        // mute if signal is not changed in 2 frames
-                       update = 2;
+                       changed = 2;
                        signal = next;
                }
        } else if(id == SIG_PCM1BIT_ON) {
+               touch_sound();
                on = ((data & mask) != 0);
+               set_realtime_render(this, on & !mute);
        } else if(id == SIG_PCM1BIT_MUTE) {
+               touch_sound();
                mute = ((data & mask) != 0);
+               set_realtime_render(this, on & !mute);
        }
 }
 
 void PCM1BIT::event_frame()
 {
-       if(update && --update == 0) {
-#ifdef PCM1BIT_HIGH_QUALITY
-               prev_vol = 0;
-#endif
+       if(changed) {
+               changed--;
        }
 }
 
-void PCM1BIT::mix(int32* buffer, int cnt)
+void PCM1BIT::mix(int32_t* buffer, int cnt)
 {
-#ifdef PCM1BIT_HIGH_QUALITY
-       uint32 cur_clock = current_clock();
-       if(update) {
-               if(sample_count < 1024) {
-                       samples_signal[sample_count] = signal;
-                       samples_out[sample_count] = (on && !mute);
-                       samples_clock[sample_count] = passed_clock(prev_clock);
-                       sample_count++;
+       if(on && !mute && changed) {
+               if(signal) {
+                       positive_clocks += get_passed_clock(prev_clock);
+               } else {
+                       negative_clocks += get_passed_clock(prev_clock);
                }
-               uint32 start_clock = 0;
-               int start_index = 0;
+               int clocks = positive_clocks + negative_clocks;
+               int sample = clocks ? (max_vol * positive_clocks - max_vol * negative_clocks) / clocks : signal ? max_vol : -max_vol;
+               
+               last_vol_l = apply_volume(sample, volume_l);
+               last_vol_r = apply_volume(sample, volume_r);
+               
                for(int i = 0; i < cnt; i++) {
-                       uint32 end_clock = ((cur_clock - prev_clock) * (i + 1)) / cnt;
-                       int on_clocks = 0, off_clocks = 0;
-                       for(int s = start_index; s < sample_count; s++) {
-                               uint32 clock = samples_clock[s];
-                               if(clock <= end_clock) {
-                                       if(samples_out[s]) {
-                                               if(samples_signal[s]) {
-                                                       on_clocks += clock - start_clock;
-                                               } else {
-                                                       off_clocks += clock - start_clock;
-                                               }
-                                       }
-                                       start_clock = clock;
-                                       start_index = s + 1;
-                               } else {
-                                       if(samples_out[s]) {
-                                               if(samples_signal[s]) {
-                                                       on_clocks += end_clock - start_clock;
-                                               } else {
-                                                       off_clocks += end_clock - start_clock;
-                                               }
-                                       }
-                                       start_clock = end_clock;
-                                       start_index = s;
-                                       break;
-                               }
-                       }
-                       int clocks = on_clocks + off_clocks;
-                       if(clocks) {
-                               prev_vol = max_vol * (on_clocks - off_clocks) / clocks;
-                       }
-                       *buffer++ += prev_vol; // L
-                       *buffer++ += prev_vol; // R
+                       *buffer++ += last_vol_l; // L
+                       *buffer++ += last_vol_r; // R
                }
-       }
-       prev_clock = cur_clock;
-       sample_count = 0;
-#else
-       if(on && !mute && signal) {
+       } else {
+               // suppress petite noise when go to mute
                for(int i = 0; i < cnt; i++) {
-                       *buffer++ += max_vol; // L
-                       *buffer++ += max_vol; // R
+                       *buffer++ += last_vol_l; // L
+                       *buffer++ += last_vol_r; // R
+                       
+                       if(last_vol_l > 0) {
+                               last_vol_l--;
+                       } else if(last_vol_l < 0) {
+                               last_vol_l++;
+                       }
+                       if(last_vol_r > 0) {
+                               last_vol_r--;
+                       } else if(last_vol_r < 0) {
+                               last_vol_r++;
+                       }
                }
        }
-#endif
+       prev_clock = get_current_clock();
+       positive_clocks = negative_clocks = 0;
 }
 
-void PCM1BIT::init(int rate, int volume)
+void PCM1BIT::set_volume(int ch, int decibel_l, int decibel_r)
 {
-       max_vol = volume;
+       volume_l = decibel_to_volume(decibel_l);
+       volume_r = decibel_to_volume(decibel_r);
 }
 
-#define STATE_VERSION  1
-
-void PCM1BIT::save_state(FILEIO* state_fio)
+void PCM1BIT::initialize_sound(int rate, int volume)
 {
-       state_fio->FputUint32(STATE_VERSION);
-       state_fio->FputInt32(this_device_id);
-       
-       state_fio->FputBool(signal);
-       state_fio->FputBool(on);
-       state_fio->FputBool(mute);
-#ifdef PCM1BIT_HIGH_QUALITY
-       state_fio->Fwrite(samples_signal, sizeof(samples_signal), 1);
-       state_fio->Fwrite(samples_out, sizeof(samples_out), 1);
-       state_fio->Fwrite(samples_clock, sizeof(samples_clock), 1);
-       state_fio->FputInt32(sample_count);
-       state_fio->FputUint32(prev_clock);
-       state_fio->FputInt32(prev_vol);
-#endif
-       state_fio->FputInt32(update);
+       max_vol = volume;
 }
 
-bool PCM1BIT::load_state(FILEIO* state_fio)
+#define STATE_VERSION  3
+
+bool PCM1BIT::process_state(FILEIO* state_fio, bool loading)
 {
-       if(state_fio->FgetUint32() != STATE_VERSION) {
-               return false;
+       if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+               return false;
+       }
+       if(!state_fio->StateCheckInt32(this_device_id)) {
+               return false;
+       }
+       state_fio->StateValue(signal);
+       state_fio->StateValue(on);
+       state_fio->StateValue(mute);
+       state_fio->StateValue(realtime);
+       state_fio->StateValue(changed);
+       state_fio->StateValue(prev_clock);
+       state_fio->StateValue(positive_clocks);
+       state_fio->StateValue(negative_clocks);
+       
+       // post process
+       if(loading) {
+               last_vol_l = last_vol_r = 0;
+               set_realtime_render(this, on & !mute);
+               //touch_sound();
        }
-       if(state_fio->FgetInt32() != this_device_id) {
-               return false;
-       }
-       signal = state_fio->FgetBool();
-       on = state_fio->FgetBool();
-       mute = state_fio->FgetBool();
-#ifdef PCM1BIT_HIGH_QUALITY
-       state_fio->Fread(samples_signal, sizeof(samples_signal), 1);
-       state_fio->Fread(samples_out, sizeof(samples_out), 1);
-       state_fio->Fread(samples_clock, sizeof(samples_clock), 1);
-       sample_count = state_fio->FgetInt32();
-       prev_clock = state_fio->FgetUint32();
-       prev_vol = state_fio->FgetInt32();
-#endif
-       update = state_fio->FgetInt32();
-       return true;
+       return true;
 }
-