lsnes rr2-β24
[lsnes.git] / src / emulation / sky / sound.cpp
blob196c48131d919596a1406e5c6c838093f31bd49e
1 #include "sound.hpp"
2 #include "romimage.hpp"
3 #include "util.hpp"
4 #include "state.hpp"
5 #include "instance.hpp"
6 #include "library/string.hpp"
7 #include "library/zip.hpp"
8 #include "library/minmax.hpp"
10 namespace sky
12 sound::sound()
14 snds = NULL;
15 rate = 128;
16 pointer = 0;
17 length = 0;
20 sound::sound(struct sounds& _snds, uint8_t _rate, uint32_t ptr, uint32_t len)
22 snds = &_snds;
23 rate = _rate;
24 pointer = ptr;
25 length = len;
28 sounds::sounds()
32 sounds::sounds(const std::vector<char>& snd, size_t samples)
34 sounddata = snd;
35 sfx.resize(samples);
36 if(snd.size() < 2 * samples + 2)
37 (stringfmt() << "Sound pointer table incomplete").throwex();
38 for(unsigned i = 0; i < samples; i++) {
39 size_t sptr = combine(snd[2 * i + 0], snd[2 * i + 1]);
40 size_t eptr = combine(snd[2 * i + 2], snd[2 * i + 3]);
41 if(sptr >= snd.size())
42 (stringfmt() << "Sound " << i << " points outside file").throwex();
43 if(eptr > snd.size())
44 (stringfmt() << "Sound " << i << " extends past the end of file").throwex();
45 if(eptr <= sptr)
46 (stringfmt() << "Sound " << i << " size invalid (must be >0)").throwex();
47 uint8_t rate = snd[sptr];
48 sfx[i] = sound(*this, rate, sptr + 1, eptr - sptr - 1);
52 sounds::sounds(const sounds& s)
54 *this = s;
57 sounds& sounds::operator=(const sounds& s)
59 if(this == &s)
60 return *this;
61 sounddata = s.sounddata;
62 sfx.resize(s.sfx.size());
63 for(unsigned i = 0; i < s.sfx.size(); i++)
64 sfx[i] = sound(*this, s.sfx[i].get_rate(), s.sfx[i].get_pointer(), s.sfx[i].get_length());
65 return *this;
68 active_sfx_dma::active_sfx_dma()
70 //End of transfer.
71 left = 0;
72 pointer = 0;
73 subsample = 0;
74 mdr = 128;
75 rate = 128;
76 _hipri = 0;
79 void active_sfx_dma::reset(const struct sound& snd)
81 rate = snd.get_rate();
82 left = 48000ULL * (256 - rate) * snd.get_length();
83 subsample = 0;
84 pointer = snd.get_pointer();
85 mdr = access(snd.get_sounds(), pointer++);
88 void active_sfx_dma::fetch(struct sounds& snds, int16_t* buffer, size_t samples)
90 while(left > 0 && samples > 0) {
91 *(buffer++) = 256 * ((int16_t)mdr - 128);
92 *(buffer++) = 256 * ((int16_t)mdr - 128);
93 subsample += 1000000;
94 while(subsample > 48000ULL * (256 - rate)) {
95 mdr = snds.access(pointer++);
96 subsample -= 48000ULL * (256 - rate);
98 left -= 1000000;
99 samples--;
101 //Fill the rest with silence.
102 for(size_t i = 0; i < samples; i++) {
103 *(buffer++) = 0;
104 *(buffer++) = 0;
108 void fetch_sfx(struct instance& inst, int16_t* buffer, size_t samples)
110 std::vector<std::pair<int16_t, int16_t>> buf;
111 buf.resize(samples);
112 inst.state.dma.fetch(inst.soundfx, buffer, samples);
113 try {
114 inst.mplayer.decode(&buf[0], samples);
115 } catch(...) {
117 for(size_t i = 0; i < samples; i++) {
118 buffer[2 * i + 0] = max(min((int32_t)buffer[2 * i + 0] + buf[i].first, 32767), -32768);
119 buffer[2 * i + 1] = max(min((int32_t)buffer[2 * i + 1] + buf[i].second, 32767), -32768);
124 sound_noise_maker::sound_noise_maker(const sounds& _snds, struct active_sfx_dma& _dma)
125 : snds(_snds), dma(_dma)
129 sound_noise_maker::~sound_noise_maker() {}
130 void sound_noise_maker::operator()(int sound, bool hipri)
132 if(!hipri && dma.hipri() && dma.busy())
133 return;
134 dma.reset(snds[sound]);
135 dma.hipri(hipri);