1 // Blip_Buffer 0.3.0. http://www.slack.net/~ant/nes-emu/
2
3 #include "../include/blip/Stereo_Buffer.h"
4
5 /* Library Copyright (C) 2004 Shay Green. Blip_Buffer is free software;
6 you can redistribute it and/or modify it under the terms of the GNU
7 General Public License as published by the Free Software Foundation;
8 either version 2 of the License, or (at your option) any later version.
9 Stereo_Buffer is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details. You should have received a copy of the GNU General
13 Public License along with Stereo_Buffer; if not, write to the Free Software
14 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15
Stereo_Buffer()16 Stereo_Buffer::Stereo_Buffer() {
17 }
18
~Stereo_Buffer()19 Stereo_Buffer::~Stereo_Buffer() {
20 }
21
set_sample_rate(long rate,int msec)22 bool Stereo_Buffer::set_sample_rate( long rate, int msec )
23 {
24 for ( int i = 0; i < buf_count; i++ ) {
25 if ( bufs [i].set_sample_rate( rate, msec ) )
26 {
27 return false;
28 }
29 }
30
31 return true;
32 }
33
clock_rate(long rate)34 void Stereo_Buffer::clock_rate( long rate )
35 {
36 for ( int i = 0; i < buf_count; i++ )
37 bufs [i].clock_rate( rate );
38 }
39
bass_freq(int bass)40 void Stereo_Buffer::bass_freq( int bass )
41 {
42 for ( unsigned i = 0; i < buf_count; i++ )
43 bufs [i].bass_freq( bass );
44 }
45
clear()46 void Stereo_Buffer::clear()
47 {
48 stereo_added = false;
49 was_stereo = false;
50 for ( int i = 0; i < buf_count; i++ )
51 bufs [i].clear();
52 }
53
end_frame(blip_time_t clock_count,bool stereo)54 void Stereo_Buffer::end_frame( blip_time_t clock_count, bool stereo )
55 {
56 for ( unsigned i = 0; i < buf_count; i++ )
57 {
58 bufs [i].end_frame( clock_count );
59 }
60 stereo_added |= stereo;
61 }
62
63
64
read_samples(blip_sample_t * out,long max_samples)65 long Stereo_Buffer::read_samples( blip_sample_t* out, long max_samples )
66 {
67 long count = bufs [0].samples_avail();
68 if ( count > max_samples / 2 )
69 count = max_samples / 2;
70 if ( count )
71 {
72 if ( stereo_added || was_stereo )
73 {
74 mix_stereo( out, count );
75
76 bufs [0].remove_samples( count );
77 bufs [1].remove_samples( count );
78 bufs [2].remove_samples( count );
79 }
80 #ifndef WANT_STEREO_SOUND
81 else
82 {
83 mix_mono( out, count );
84
85 bufs [0].remove_samples( count );
86
87 bufs [1].remove_silence( count );
88 bufs [2].remove_silence( count );
89 }
90 #endif
91
92 // to do: this might miss opportunities for optimization
93 if ( !bufs [0].samples_avail() ) {
94 was_stereo = stereo_added;
95 stereo_added = false;
96 }
97 }
98
99 return count * 2;
100 }
101
mix_stereo(blip_sample_t * out,long count)102 void Stereo_Buffer::mix_stereo( blip_sample_t* out, long count )
103 {
104 Blip_Reader left;
105 Blip_Reader right;
106 Blip_Reader center;
107
108 left.begin( bufs [1] );
109 right.begin( bufs [2] );
110 int bass = center.begin( bufs [0] );
111
112 while ( count-- )
113 {
114 int c = center.read();
115 out [0] = c + left.read();
116 out [1] = c + right.read();
117 out += 2;
118
119 center.next( bass );
120 left.next( bass );
121 right.next( bass );
122 }
123
124 center.end( bufs [0] );
125 right.end( bufs [2] );
126 left.end( bufs [1] );
127 }
128
mix_stereo(float * out,long count)129 void Stereo_Buffer::mix_stereo( float* out, long count )
130 {
131 Blip_Reader left;
132 Blip_Reader right;
133 Blip_Reader center;
134
135 left.begin( bufs [1] );
136 right.begin( bufs [2] );
137 int bass = center.begin( bufs [0] );
138
139 while ( count-- )
140 {
141 int c = center.read();
142 out [0] = (float)(c + left.read()) / 32768;
143 out [1] = (float)(c + right.read()) / 32768;
144 out += 2;
145
146 center.next( bass );
147 left.next( bass );
148 right.next( bass );
149 }
150
151 center.end( bufs [0] );
152 right.end( bufs [2] );
153 left.end( bufs [1] );
154 }
155
156 #ifndef WANT_STEREO_SOUND
mix_mono(blip_sample_t * out,long count)157 void Stereo_Buffer::mix_mono( blip_sample_t* out, long count )
158 {
159 Blip_Reader in;
160 int bass = in.begin( bufs [0] );
161
162 while ( count-- )
163 {
164 int sample = in.read();
165 out [0] = sample;
166 out [1] = sample;
167 out += 2;
168 in.next( bass );
169 }
170
171 in.end( bufs [0] );
172 }
173
mix_mono(float * out,long count)174 void Stereo_Buffer::mix_mono( float* out, long count )
175 {
176 Blip_Reader in;
177 int bass = in.begin( bufs [0] );
178
179 while ( count-- )
180 {
181 int sample = in.read();
182 out [0] = (float)(sample) / 32768;
183 out [1] = (float)(sample) / 32768;
184 out += 2;
185 in.next( bass );
186 }
187
188 in.end( bufs [0] );
189 }
190 #endif
191
192