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