Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Multi_Buffer.cpp
2 views
1
2
// Blip_Buffer 0.4.0. http://www.slack.net/~ant/
3
4
#include "Multi_Buffer.h"
5
6
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
7
can redistribute it and/or modify it under the terms of the GNU Lesser
8
General Public License as published by the Free Software Foundation; either
9
version 2.1 of the License, or (at your option) any later version. This
10
module is distributed in the hope that it will be useful, but WITHOUT ANY
11
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
13
more details. You should have received a copy of the GNU Lesser General
14
Public License along with this module; if not, write to the Free Software
15
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
17
#include "blargg_source.h"
18
19
Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
20
{
21
length_ = 0;
22
sample_rate_ = 0;
23
channels_changed_count_ = 1;
24
}
25
26
blargg_err_t Multi_Buffer::set_channel_count( int )
27
{
28
return 0;
29
}
30
31
Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
32
{
33
}
34
35
Mono_Buffer::~Mono_Buffer()
36
{
37
}
38
39
blargg_err_t Mono_Buffer::set_sample_rate( long rate, int msec )
40
{
41
RETURN_ERR( buf.set_sample_rate( rate, msec ) );
42
return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
43
}
44
45
// Silent_Buffer
46
47
Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
48
{
49
chan.left = NULL;
50
chan.center = NULL;
51
chan.right = NULL;
52
}
53
54
// Mono_Buffer
55
56
Mono_Buffer::channel_t Mono_Buffer::channel( int )
57
{
58
channel_t ch;
59
ch.center = &buf;
60
ch.left = &buf;
61
ch.right = &buf;
62
return ch;
63
}
64
65
void Mono_Buffer::end_frame( blip_time_t t, bool )
66
{
67
buf.end_frame( t );
68
}
69
70
// Stereo_Buffer
71
72
Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
73
{
74
chan.center = &bufs [0];
75
chan.left = &bufs [1];
76
chan.right = &bufs [2];
77
}
78
79
Stereo_Buffer::~Stereo_Buffer()
80
{
81
}
82
83
blargg_err_t Stereo_Buffer::set_sample_rate( long rate, int msec )
84
{
85
for ( int i = 0; i < buf_count; i++ )
86
RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
87
return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
88
}
89
90
void Stereo_Buffer::clock_rate( long rate )
91
{
92
for ( int i = 0; i < buf_count; i++ )
93
bufs [i].clock_rate( rate );
94
}
95
96
void Stereo_Buffer::bass_freq( int bass )
97
{
98
for ( unsigned i = 0; i < buf_count; i++ )
99
bufs [i].bass_freq( bass );
100
}
101
102
void Stereo_Buffer::clear()
103
{
104
stereo_added = false;
105
was_stereo = false;
106
for ( int i = 0; i < buf_count; i++ )
107
bufs [i].clear();
108
}
109
110
void Stereo_Buffer::end_frame( blip_time_t clock_count, bool stereo )
111
{
112
for ( unsigned i = 0; i < buf_count; i++ )
113
bufs [i].end_frame( clock_count );
114
115
stereo_added |= stereo;
116
}
117
118
long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
119
{
120
require( !(count & 1) ); // count must be even
121
count = (unsigned) count / 2;
122
123
long avail = bufs [0].samples_avail();
124
if ( count > avail )
125
count = avail;
126
if ( count )
127
{
128
if ( stereo_added || was_stereo )
129
{
130
mix_stereo( out, count );
131
132
bufs [0].remove_samples( count );
133
bufs [1].remove_samples( count );
134
bufs [2].remove_samples( count );
135
}
136
else
137
{
138
mix_mono( out, count );
139
140
bufs [0].remove_samples( count );
141
142
bufs [1].remove_silence( count );
143
bufs [2].remove_silence( count );
144
}
145
146
// to do: this might miss opportunities for optimization
147
if ( !bufs [0].samples_avail() ) {
148
was_stereo = stereo_added;
149
stereo_added = false;
150
}
151
}
152
153
return count * 2;
154
}
155
156
void Stereo_Buffer::mix_stereo( blip_sample_t* out, long count )
157
{
158
Blip_Reader left;
159
Blip_Reader right;
160
Blip_Reader center;
161
162
left.begin( bufs [1] );
163
right.begin( bufs [2] );
164
int bass = center.begin( bufs [0] );
165
166
while ( count-- )
167
{
168
int c = center.read();
169
long l = c + left.read();
170
long r = c + right.read();
171
center.next( bass );
172
out [0] = l;
173
out [1] = r;
174
out += 2;
175
176
if ( (BOOST::int16_t) l != l )
177
out [-2] = 0x7FFF - (l >> 24);
178
179
left.next( bass );
180
right.next( bass );
181
182
if ( (BOOST::int16_t) r != r )
183
out [-1] = 0x7FFF - (r >> 24);
184
}
185
186
center.end( bufs [0] );
187
right.end( bufs [2] );
188
left.end( bufs [1] );
189
}
190
191
void Stereo_Buffer::mix_mono( blip_sample_t* out, long count )
192
{
193
Blip_Reader in;
194
int bass = in.begin( bufs [0] );
195
196
while ( count-- )
197
{
198
long s = in.read();
199
in.next( bass );
200
out [0] = s;
201
out [1] = s;
202
out += 2;
203
204
if ( (BOOST::int16_t) s != s ) {
205
s = 0x7FFF - (s >> 24);
206
out [-2] = s;
207
out [-1] = s;
208
}
209
}
210
211
in.end( bufs [0] );
212
}
213
214
215