OSDN Git Service

[VM][FMTOWNS][MEMORY] Fix setup around memory banks by I/O 0404h and 0480h.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pv1000 / psg.cpp
1 /*
2         CASIO PV-1000 Emulator 'ePV-1000'
3
4         Author : Takeda.Toshiya
5         Date   : 2006.11.16 -
6
7         [ psg ]
8 */
9
10 #include <math.h>
11 #include "./psg.h"
12 #include "../../types/util_sound.h"
13
14 #define PSG_CLOCK
15 #define PSG_VOLUME      8192
16
17 namespace PV1000 {
18
19 void PSG::reset()
20 {
21         touch_sound();
22         memset(ch, 0, sizeof(ch));
23 }
24
25 void PSG::write_io8(uint32_t addr, uint32_t data)
26 {
27         touch_sound();
28         ch[addr & 3].period = 0x3f - (data & 0x3f);
29 }
30
31 void PSG::initialize_sound(int rate)
32 {
33         diff = (int)(1.3 * (double)CPU_CLOCKS / (double)rate + 0.5);
34 }
35
36 void PSG::mix(int32_t* buffer, int cnt)
37 {
38         // create sound buffer
39         for(int i = 0; i < cnt; i++) {
40                 int vol = 0;
41                 for(int j = 0; j < 3; j++) {
42                         if(!ch[j].period) {
43                                 continue;
44                         }
45                         bool prev_signal = ch[j].signal;
46                         int prev_count = ch[j].count;
47                         ch[j].count -= diff;
48                         if(ch[j].count < 0) {
49                                 ch[j].count += ch[j].period << 8;
50                                 ch[j].signal = !ch[j].signal;
51                         }
52                         int vol_tmp = (prev_signal != ch[j].signal && prev_count < diff) ? (PSG_VOLUME * (2 * prev_count - diff)) / diff : PSG_VOLUME;
53                         vol += prev_signal ? vol_tmp : -vol_tmp;
54                 }
55                 *buffer++ += apply_volume(vol, volume_l); // L
56                 *buffer++ += apply_volume(vol, volume_l); // R
57         }
58 }
59
60 void PSG::set_volume(int ch, int decibel_l, int decibel_r)
61 {
62         volume_l = decibel_to_volume(decibel_l);
63         volume_r = decibel_to_volume(decibel_r);
64 }
65
66 #define STATE_VERSION   1
67
68 bool PSG::process_state(FILEIO* state_fio, bool loading)
69 {
70         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
71                 return false;
72         }
73         if(!state_fio->StateCheckInt32(this_device_id)) {
74                 return false;
75         }
76         for(int i = 0; i < 3; i++) {
77                 state_fio->StateValue(ch[i].period);
78         }
79         return true;
80 }
81
82 }