/src/vlc/contrib/contrib-build/game-music-emu/gme/Multi_Buffer.cpp
Line | Count | Source |
1 | | // Blip_Buffer 0.4.1. http://www.slack.net/~ant/ |
2 | | |
3 | | #include "Multi_Buffer.h" |
4 | | |
5 | | /* Copyright (C) 2003-2006 Shay Green. This module is free software; you |
6 | | can redistribute it and/or modify it under the terms of the GNU Lesser |
7 | | General Public License as published by the Free Software Foundation; either |
8 | | version 2.1 of the License, or (at your option) any later version. This |
9 | | module is distributed in the hope that it will be useful, but WITHOUT ANY |
10 | | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
11 | | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
12 | | details. You should have received a copy of the GNU Lesser General Public |
13 | | License along with this module; if not, write to the Free Software Foundation, |
14 | | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ |
15 | | |
16 | | #include "blargg_source.h" |
17 | | |
18 | | #ifdef BLARGG_ENABLE_OPTIMIZER |
19 | | #include BLARGG_ENABLE_OPTIMIZER |
20 | | #endif |
21 | | |
22 | 3.00k | Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf ) |
23 | 3.00k | { |
24 | 3.00k | length_ = 0; |
25 | 3.00k | sample_rate_ = 0; |
26 | 3.00k | channels_changed_count_ = 1; |
27 | 3.00k | } |
28 | | |
29 | 3.04k | blargg_err_t Multi_Buffer::set_channel_count( int ) { return 0; } |
30 | | |
31 | | // Silent_Buffer |
32 | | |
33 | 0 | Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse |
34 | 0 | { |
35 | | // TODO: better to use empty Blip_Buffer so caller never has to check for NULL? |
36 | 0 | chan.left = 0; |
37 | 0 | chan.center = 0; |
38 | 0 | chan.right = 0; |
39 | 0 | } |
40 | | |
41 | | // Mono_Buffer |
42 | | |
43 | 0 | Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 ) |
44 | 0 | { |
45 | 0 | chan.center = &buf; |
46 | 0 | chan.left = &buf; |
47 | 0 | chan.right = &buf; |
48 | 0 | } |
49 | | |
50 | 0 | Mono_Buffer::~Mono_Buffer() { } |
51 | | |
52 | | blargg_err_t Mono_Buffer::set_sample_rate( long rate, int msec ) |
53 | 0 | { |
54 | 0 | RETURN_ERR( buf.set_sample_rate( rate, msec ) ); |
55 | 0 | return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() ); |
56 | 0 | } |
57 | | |
58 | | // Stereo_Buffer |
59 | | |
60 | 0 | Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 ) |
61 | 0 | { |
62 | 0 | chan.center = &bufs [0]; |
63 | 0 | chan.left = &bufs [1]; |
64 | 0 | chan.right = &bufs [2]; |
65 | 0 | } |
66 | | |
67 | 0 | Stereo_Buffer::~Stereo_Buffer() { } |
68 | | |
69 | | blargg_err_t Stereo_Buffer::set_sample_rate( long rate, int msec ) |
70 | 0 | { |
71 | 0 | for ( int i = 0; i < buf_count; i++ ) |
72 | 0 | RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) ); |
73 | 0 | return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() ); |
74 | 0 | } |
75 | | |
76 | | void Stereo_Buffer::clock_rate( uint32_t rate ) |
77 | 0 | { |
78 | 0 | for ( int i = 0; i < buf_count; i++ ) |
79 | 0 | bufs [i].clock_rate( rate ); |
80 | 0 | } |
81 | | |
82 | | void Stereo_Buffer::bass_freq( int bass ) |
83 | 0 | { |
84 | 0 | for ( int i = 0; i < buf_count; i++ ) |
85 | 0 | bufs [i].bass_freq( bass ); |
86 | 0 | } |
87 | | |
88 | | void Stereo_Buffer::clear() |
89 | 0 | { |
90 | 0 | stereo_added = 0; |
91 | 0 | was_stereo = false; |
92 | 0 | for ( int i = 0; i < buf_count; i++ ) |
93 | 0 | bufs [i].clear(); |
94 | 0 | } |
95 | | |
96 | | void Stereo_Buffer::end_frame( blip_time_t clock_count ) |
97 | 0 | { |
98 | 0 | stereo_added = 0; |
99 | 0 | for ( int i = 0; i < buf_count; i++ ) |
100 | 0 | { |
101 | 0 | stereo_added |= bufs [i].clear_modified() << i; |
102 | 0 | bufs [i].end_frame( clock_count ); |
103 | 0 | } |
104 | 0 | } |
105 | | |
106 | | long Stereo_Buffer::read_samples( blip_sample_t* out, long count ) |
107 | 0 | { |
108 | 0 | require( !(count & 1) ); // count must be even |
109 | 0 | count = (unsigned) count / 2; |
110 | |
|
111 | 0 | long avail = bufs [0].samples_avail(); |
112 | 0 | if ( count > avail ) |
113 | 0 | count = avail; |
114 | 0 | if ( count ) |
115 | 0 | { |
116 | 0 | int bufs_used = stereo_added | was_stereo; |
117 | | //debug_printf( "%X\n", bufs_used ); |
118 | 0 | if ( bufs_used <= 1 ) |
119 | 0 | { |
120 | 0 | mix_mono( out, count ); |
121 | 0 | bufs [0].remove_samples( count ); |
122 | 0 | bufs [1].remove_silence( count ); |
123 | 0 | bufs [2].remove_silence( count ); |
124 | 0 | } |
125 | 0 | else if ( bufs_used & 1 ) |
126 | 0 | { |
127 | 0 | mix_stereo( out, count ); |
128 | 0 | bufs [0].remove_samples( count ); |
129 | 0 | bufs [1].remove_samples( count ); |
130 | 0 | bufs [2].remove_samples( count ); |
131 | 0 | } |
132 | 0 | else |
133 | 0 | { |
134 | 0 | mix_stereo_no_center( out, count ); |
135 | 0 | bufs [0].remove_silence( count ); |
136 | 0 | bufs [1].remove_samples( count ); |
137 | 0 | bufs [2].remove_samples( count ); |
138 | 0 | } |
139 | | |
140 | | // to do: this might miss opportunities for optimization |
141 | 0 | if ( !bufs [0].samples_avail() ) |
142 | 0 | { |
143 | 0 | was_stereo = stereo_added; |
144 | 0 | stereo_added = 0; |
145 | 0 | } |
146 | 0 | } |
147 | |
|
148 | 0 | return count * 2; |
149 | 0 | } |
150 | | |
151 | | void Stereo_Buffer::mix_stereo( blip_sample_t* out_, int32_t count ) |
152 | 0 | { |
153 | 0 | blip_sample_t* BLIP_RESTRICT out = out_; |
154 | 0 | int const bass = BLIP_READER_BASS( bufs [1] ); |
155 | 0 | BLIP_READER_BEGIN( left, bufs [1] ); |
156 | 0 | BLIP_READER_BEGIN( right, bufs [2] ); |
157 | 0 | BLIP_READER_BEGIN( center, bufs [0] ); |
158 | |
|
159 | 0 | for ( ; count; --count ) |
160 | 0 | { |
161 | 0 | int c = BLIP_READER_READ( center ); |
162 | 0 | int32_t l = c + BLIP_READER_READ( left ); |
163 | 0 | int32_t r = c + BLIP_READER_READ( right ); |
164 | 0 | if ( (int16_t) l != l ) |
165 | 0 | l = 0x7FFF - (l >> 24); |
166 | |
|
167 | 0 | BLIP_READER_NEXT( center, bass ); |
168 | 0 | if ( (int16_t) r != r ) |
169 | 0 | r = 0x7FFF - (r >> 24); |
170 | |
|
171 | 0 | BLIP_READER_NEXT( left, bass ); |
172 | 0 | BLIP_READER_NEXT( right, bass ); |
173 | |
|
174 | 0 | out [0] = l; |
175 | 0 | out [1] = r; |
176 | 0 | out += 2; |
177 | 0 | } |
178 | |
|
179 | 0 | BLIP_READER_END( center, bufs [0] ); |
180 | 0 | BLIP_READER_END( right, bufs [2] ); |
181 | 0 | BLIP_READER_END( left, bufs [1] ); |
182 | 0 | } |
183 | | |
184 | | void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, int32_t count ) |
185 | 0 | { |
186 | 0 | blip_sample_t* BLIP_RESTRICT out = out_; |
187 | 0 | int const bass = BLIP_READER_BASS( bufs [1] ); |
188 | 0 | BLIP_READER_BEGIN( left, bufs [1] ); |
189 | 0 | BLIP_READER_BEGIN( right, bufs [2] ); |
190 | |
|
191 | 0 | for ( ; count; --count ) |
192 | 0 | { |
193 | 0 | int32_t l = BLIP_READER_READ( left ); |
194 | 0 | if ( (int16_t) l != l ) |
195 | 0 | l = 0x7FFF - (l >> 24); |
196 | |
|
197 | 0 | int32_t r = BLIP_READER_READ( right ); |
198 | 0 | if ( (int16_t) r != r ) |
199 | 0 | r = 0x7FFF - (r >> 24); |
200 | |
|
201 | 0 | BLIP_READER_NEXT( left, bass ); |
202 | 0 | BLIP_READER_NEXT( right, bass ); |
203 | |
|
204 | 0 | out [0] = l; |
205 | 0 | out [1] = r; |
206 | 0 | out += 2; |
207 | 0 | } |
208 | |
|
209 | 0 | BLIP_READER_END( right, bufs [2] ); |
210 | 0 | BLIP_READER_END( left, bufs [1] ); |
211 | 0 | } |
212 | | |
213 | | void Stereo_Buffer::mix_mono( blip_sample_t* out_, int32_t count ) |
214 | 0 | { |
215 | 0 | blip_sample_t* BLIP_RESTRICT out = out_; |
216 | 0 | int const bass = BLIP_READER_BASS( bufs [0] ); |
217 | 0 | BLIP_READER_BEGIN( center, bufs [0] ); |
218 | |
|
219 | 0 | for ( ; count; --count ) |
220 | 0 | { |
221 | 0 | int32_t s = BLIP_READER_READ( center ); |
222 | 0 | if ( (int16_t) s != s ) |
223 | 0 | s = 0x7FFF - (s >> 24); |
224 | |
|
225 | 0 | BLIP_READER_NEXT( center, bass ); |
226 | 0 | out [0] = s; |
227 | 0 | out [1] = s; |
228 | 0 | out += 2; |
229 | 0 | } |
230 | |
|
231 | 0 | BLIP_READER_END( center, bufs [0] ); |
232 | 0 | } |