summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/multi_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/multi_buffer.c')
-rw-r--r--apps/codecs/libgme/multi_buffer.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/apps/codecs/libgme/multi_buffer.c b/apps/codecs/libgme/multi_buffer.c
new file mode 100644
index 0000000000..26cb8cdec6
--- /dev/null
+++ b/apps/codecs/libgme/multi_buffer.c
@@ -0,0 +1,226 @@
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
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 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// Stereo_Buffer
23
24void Buffer_init( struct Stereo_Buffer* this )
25{
26 Blip_init( &this->bufs [0] );
27 Blip_init( &this->bufs [1] );
28 Blip_init( &this->bufs [2] );
29
30 this->chan.center = &this->bufs [0];
31 this->chan.left = &this->bufs [1];
32 this->chan.right = &this->bufs [2];
33
34 this->length_ = 0;
35 this->sample_rate_ = 0;
36 this->channels_changed_count_ = 1;
37 this->samples_per_frame_ = 2;
38}
39
40blargg_err_t Buffer_set_sample_rate( struct Stereo_Buffer* this, long rate, int msec )
41{
42 int i;
43 for ( i = 0; i < buf_count; i++ )
44 RETURN_ERR( Blip_set_sample_rate( &this->bufs[i], rate, msec ) );
45
46 this->sample_rate_ = Blip_sample_rate( &this->bufs [0] );
47 this->length_ = Blip_length( &this->bufs [0] );
48 return 0;
49}
50
51void Buffer_clock_rate( struct Stereo_Buffer* this, long rate )
52{
53 int i;
54 for ( i = 0; i < buf_count; i++ )
55 Blip_set_clock_rate( &this->bufs [i], rate );
56}
57
58void Buffer_bass_freq( struct Stereo_Buffer* this, int bass )
59{
60 unsigned i;
61 for ( i = 0; i < buf_count; i++ )
62 Blip_bass_freq( &this->bufs [i], bass );
63}
64
65struct channel_t Buffer_channel( struct Stereo_Buffer* this )
66{
67 return this->chan;
68}
69
70void Buffer_clear( struct Stereo_Buffer* this )
71{
72 this->stereo_added = 0;
73 this->was_stereo = false;
74 int i;
75 for ( i = 0; i < buf_count; i++ )
76 Blip_clear( &this->bufs [i], 1 );
77}
78
79void Buffer_end_frame( struct Stereo_Buffer* this, blip_time_t clock_count )
80{
81 this->stereo_added = 0;
82 unsigned i;
83 for ( i = 0; i < buf_count; i++ )
84 {
85 this->stereo_added |= Blip_clear_modified( &this->bufs [i] ) << i;
86 Blip_end_frame( &this->bufs [i], clock_count );
87 }
88}
89
90long Buffer_read_samples( struct Stereo_Buffer* this, blip_sample_t* out, long count )
91{
92 require( !(count & 1) ); // count must be even
93 count = (unsigned) count / 2;
94
95 long avail = Blip_samples_avail( &this->bufs [0] );
96 if ( count > avail )
97 count = avail;
98 if ( count )
99 {
100 int bufs_used = this->stereo_added | this->was_stereo;
101 //dprintf( "%X\n", bufs_used );
102 if ( bufs_used <= 1 )
103 {
104 Buffer_mix_mono( this, out, count );
105 Blip_remove_samples( &this->bufs [0], count );
106 Blip_remove_silence( &this->bufs [1], count );
107 Blip_remove_silence( &this->bufs [2], count );
108 }
109 else if ( bufs_used & 1 )
110 {
111 Buffer_mix_stereo( this, out, count );
112 Blip_remove_samples( &this->bufs [0], count );
113 Blip_remove_samples( &this->bufs [1], count );
114 Blip_remove_samples( &this->bufs [2], count );
115 }
116 else
117 {
118 Buffer_mix_stereo_no_center( this, out, count );
119 Blip_remove_silence( &this->bufs [0], count );
120 Blip_remove_samples( &this->bufs [1], count );
121 Blip_remove_samples( &this->bufs [2], count );
122 }
123
124 // to do: this might miss opportunities for optimization
125 if ( !Blip_samples_avail( &this->bufs [0] ) )
126 {
127 this->was_stereo = this->stereo_added;
128 this->stereo_added = 0;
129 }
130 }
131
132 return count * 2;
133}
134
135unsigned Buffer_channels_changed_count( struct Stereo_Buffer* this )
136{
137 return this->channels_changed_count_;
138}
139
140void Buffer_channels_changed( struct Stereo_Buffer* this )
141{
142 this->channels_changed_count_++;
143}
144
145void Buffer_mix_stereo( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count )
146{
147 blip_sample_t* BLIP_RESTRICT out = out_;
148 int const bass = BLIP_READER_BASS( this->bufs [1] );
149 BLIP_READER_BEGIN( left, this->bufs [1] );
150 BLIP_READER_BEGIN( right, this->bufs [2] );
151 BLIP_READER_BEGIN( center, this->bufs [0] );
152
153 for ( ; count; --count )
154 {
155 int c = BLIP_READER_READ( center );
156 blargg_long l = c + BLIP_READER_READ( left );
157 blargg_long r = c + BLIP_READER_READ( right );
158 if ( (int16_t) l != l )
159 l = 0x7FFF - (l >> 24);
160
161 BLIP_READER_NEXT( center, bass );
162 if ( (int16_t) r != r )
163 r = 0x7FFF - (r >> 24);
164
165 BLIP_READER_NEXT( left, bass );
166 BLIP_READER_NEXT( right, bass );
167
168 out [0] = l;
169 out [1] = r;
170 out += 2;
171 }
172
173 BLIP_READER_END( center, this->bufs [0] );
174 BLIP_READER_END( right, this->bufs [2] );
175 BLIP_READER_END( left, this->bufs [1] );
176}
177
178void Buffer_mix_stereo_no_center( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count )
179{
180 blip_sample_t* BLIP_RESTRICT out = out_;
181 int const bass = BLIP_READER_BASS( this->bufs [1] );
182 BLIP_READER_BEGIN( left, this->bufs [1] );
183 BLIP_READER_BEGIN( right, this->bufs [2] );
184
185 for ( ; count; --count )
186 {
187 blargg_long l = BLIP_READER_READ( left );
188 if ( (int16_t) l != l )
189 l = 0x7FFF - (l >> 24);
190
191 blargg_long r = BLIP_READER_READ( right );
192 if ( (int16_t) r != r )
193 r = 0x7FFF - (r >> 24);
194
195 BLIP_READER_NEXT( left, bass );
196 BLIP_READER_NEXT( right, bass );
197
198 out [0] = l;
199 out [1] = r;
200 out += 2;
201 }
202
203 BLIP_READER_END( right, this->bufs [2] );
204 BLIP_READER_END( left, this->bufs [1] );
205}
206
207void Buffer_mix_mono( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count )
208{
209 blip_sample_t* BLIP_RESTRICT out = out_;
210 int const bass = BLIP_READER_BASS( this->bufs [0] );
211 BLIP_READER_BEGIN( center, this->bufs [0] );
212
213 for ( ; count; --count )
214 {
215 blargg_long s = BLIP_READER_READ( center );
216 if ( (int16_t) s != s )
217 s = 0x7FFF - (s >> 24);
218
219 BLIP_READER_NEXT( center, bass );
220 out [0] = s;
221 out [1] = s;
222 out += 2;
223 }
224
225 BLIP_READER_END( center, this->bufs [0] );
226}