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