summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/track_filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/track_filter.c')
-rw-r--r--apps/codecs/libgme/track_filter.c588
1 files changed, 294 insertions, 294 deletions
diff --git a/apps/codecs/libgme/track_filter.c b/apps/codecs/libgme/track_filter.c
index 4776dcc7df..d0d75f2ded 100644
--- a/apps/codecs/libgme/track_filter.c
+++ b/apps/codecs/libgme/track_filter.c
@@ -1,294 +1,294 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/ 1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2 2
3#include "track_filter.h" 3#include "track_filter.h"
4 4
5/* Copyright (C) 2003-2008 Shay Green. This module is free software; you 5/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser 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 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 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 9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 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 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, 13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15 15
16#include "blargg_source.h" 16#include "blargg_source.h"
17 17
18int const fade_block_size = 512; 18int const fade_block_size = 512;
19int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift) 19int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
20int const silence_threshold = 8; 20int const silence_threshold = 8;
21 21
22void track_create( struct Track_Filter* this ) 22void track_create( struct Track_Filter* this )
23{ 23{
24 this->emu_ = NULL; 24 this->emu_ = NULL;
25 this->setup_.max_initial = 0; 25 this->setup_.max_initial = 0;
26 this->setup_.lookahead = 0; 26 this->setup_.lookahead = 0;
27 this->setup_.max_silence = indefinite_count; 27 this->setup_.max_silence = indefinite_count;
28 this->silence_ignored_ = false; 28 this->silence_ignored_ = false;
29 track_stop( this ); 29 track_stop( this );
30} 30}
31 31
32blargg_err_t track_init( struct Track_Filter* this, void* emu ) 32blargg_err_t track_init( struct Track_Filter* this, void* emu )
33{ 33{
34 this->emu_ = emu; 34 this->emu_ = emu;
35 return 0; 35 return 0;
36} 36}
37 37
38static void clear_time_vars( struct Track_Filter* this ) 38static void clear_time_vars( struct Track_Filter* this )
39{ 39{
40 this->emu_time = this->buf_remain; 40 this->emu_time = this->buf_remain;
41 this->out_time = 0; 41 this->out_time = 0;
42 this->silence_time = 0; 42 this->silence_time = 0;
43 this->silence_count = 0; 43 this->silence_count = 0;
44} 44}
45 45
46void track_stop( struct Track_Filter* this ) 46void track_stop( struct Track_Filter* this )
47{ 47{
48 this->emu_track_ended_ = true; 48 this->emu_track_ended_ = true;
49 this->track_ended_ = true; 49 this->track_ended_ = true;
50 this->fade_start = indefinite_count; 50 this->fade_start = indefinite_count;
51 this->fade_step = 1; 51 this->fade_step = 1;
52 this->buf_remain = 0; 52 this->buf_remain = 0;
53 this->emu_error = NULL; 53 this->emu_error = NULL;
54 clear_time_vars( this ); 54 clear_time_vars( this );
55} 55}
56 56
57blargg_err_t track_start( struct Track_Filter* this ) 57blargg_err_t track_start( struct Track_Filter* this )
58{ 58{
59 this->emu_error = NULL; 59 this->emu_error = NULL;
60 track_stop( this ); 60 track_stop( this );
61 61
62 this->emu_track_ended_ = false; 62 this->emu_track_ended_ = false;
63 this->track_ended_ = false; 63 this->track_ended_ = false;
64 64
65 if ( !this->silence_ignored_ ) 65 if ( !this->silence_ignored_ )
66 { 66 {
67 // play until non-silence or end of track 67 // play until non-silence or end of track
68 while ( this->emu_time < this->setup_.max_initial ) 68 while ( this->emu_time < this->setup_.max_initial )
69 { 69 {
70 fill_buf( this ); 70 fill_buf( this );
71 if ( this->buf_remain | this->emu_track_ended_ ) 71 if ( this->buf_remain | this->emu_track_ended_ )
72 break; 72 break;
73 } 73 }
74 } 74 }
75 75
76 clear_time_vars( this ); 76 clear_time_vars( this );
77 return this->emu_error; 77 return this->emu_error;
78} 78}
79 79
80static void end_track_if_error( struct Track_Filter* this, blargg_err_t err ) 80static void end_track_if_error( struct Track_Filter* this, blargg_err_t err )
81{ 81{
82 if ( err ) 82 if ( err )
83 { 83 {
84 this->emu_error = err; 84 this->emu_error = err;
85 this->emu_track_ended_ = true; 85 this->emu_track_ended_ = true;
86 } 86 }
87} 87}
88 88
89blargg_err_t track_skip( struct Track_Filter* this, int count ) 89blargg_err_t track_skip( struct Track_Filter* this, int count )
90{ 90{
91 this->emu_error = NULL; 91 this->emu_error = NULL;
92 this->out_time += count; 92 this->out_time += count;
93 93
94 // remove from silence and buf first 94 // remove from silence and buf first
95 { 95 {
96 int n = min( count, this->silence_count ); 96 int n = min( count, this->silence_count );
97 this->silence_count -= n; 97 this->silence_count -= n;
98 count -= n; 98 count -= n;
99 99
100 n = min( count, this->buf_remain ); 100 n = min( count, this->buf_remain );
101 this->buf_remain -= n; 101 this->buf_remain -= n;
102 count -= n; 102 count -= n;
103 } 103 }
104 104
105 if ( count && !this->emu_track_ended_ ) 105 if ( count && !this->emu_track_ended_ )
106 { 106 {
107 this->emu_time += count; 107 this->emu_time += count;
108 this->silence_time = this->emu_time; // would otherwise be invalid 108 this->silence_time = this->emu_time; // would otherwise be invalid
109 end_track_if_error( this, skip_( this->emu_, count ) ); 109 end_track_if_error( this, skip_( this->emu_, count ) );
110 } 110 }
111 111
112 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended 112 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
113 this->track_ended_ |= this->emu_track_ended_; 113 this->track_ended_ |= this->emu_track_ended_;
114 114
115 return this->emu_error; 115 return this->emu_error;
116} 116}
117 117
118blargg_err_t skippy_( struct Track_Filter* this, int count ) 118blargg_err_t skippy_( struct Track_Filter* this, int count )
119{ 119{
120 while ( count && !this->emu_track_ended_ ) 120 while ( count && !this->emu_track_ended_ )
121 { 121 {
122 int n = buf_size; 122 int n = buf_size;
123 if ( n > count ) 123 if ( n > count )
124 n = count; 124 n = count;
125 count -= n; 125 count -= n;
126 RETURN_ERR( play_( this->emu_, n, this->buf ) ); 126 RETURN_ERR( play_( this->emu_, n, this->buf ) );
127 } 127 }
128 return 0; 128 return 0;
129} 129}
130 130
131// Fading 131// Fading
132 132
133void track_set_fade( struct Track_Filter* this, int start, int length ) 133void track_set_fade( struct Track_Filter* this, int start, int length )
134{ 134{
135 this->fade_start = start; 135 this->fade_start = start;
136 this->fade_step = length / (fade_block_size * fade_shift); 136 this->fade_step = length / (fade_block_size * fade_shift);
137 if ( this->fade_step < 1 ) 137 if ( this->fade_step < 1 )
138 this->fade_step = 1; 138 this->fade_step = 1;
139} 139}
140 140
141static bool is_fading( struct Track_Filter* this ) 141static bool is_fading( struct Track_Filter* this )
142{ 142{
143 return this->out_time >= this->fade_start && this->fade_start != indefinite_count; 143 return this->out_time >= this->fade_start && this->fade_start != indefinite_count;
144} 144}
145 145
146// unit / pow( 2.0, (double) x / step ) 146// unit / pow( 2.0, (double) x / step )
147static int int_log( int x, int step, int unit ) 147static int int_log( int x, int step, int unit )
148{ 148{
149 int shift = x / step; 149 int shift = x / step;
150 int fraction = (x - shift * step) * unit / step; 150 int fraction = (x - shift * step) * unit / step;
151 return ((unit - fraction) + (fraction >> 1)) >> shift; 151 return ((unit - fraction) + (fraction >> 1)) >> shift;
152} 152}
153 153
154static void handle_fade( struct Track_Filter* this, sample_t out [], int out_count ) 154static void handle_fade( struct Track_Filter* this, sample_t out [], int out_count )
155{ 155{
156 int i; 156 int i;
157 for ( i = 0; i < out_count; i += fade_block_size ) 157 for ( i = 0; i < out_count; i += fade_block_size )
158 { 158 {
159 int const shift = 14; 159 int const shift = 14;
160 int const unit = 1 << shift; 160 int const unit = 1 << shift;
161 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size, 161 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
162 this->fade_step, unit ); 162 this->fade_step, unit );
163 if ( gain < (unit >> fade_shift) ) 163 if ( gain < (unit >> fade_shift) )
164 this->track_ended_ = this->emu_track_ended_ = true; 164 this->track_ended_ = this->emu_track_ended_ = true;
165 165
166 sample_t* io = &out [i]; 166 sample_t* io = &out [i];
167 for ( int count = min( fade_block_size, out_count - i ); count; --count ) 167 for ( int count = min( fade_block_size, out_count - i ); count; --count )
168 { 168 {
169 *io = (sample_t) ((*io * gain) >> shift); 169 *io = (sample_t) ((*io * gain) >> shift);
170 ++io; 170 ++io;
171 } 171 }
172 } 172 }
173} 173}
174 174
175// Silence detection 175// Silence detection
176 176
177static void emu_play( struct Track_Filter* this, sample_t out [], int count ) 177static void emu_play( struct Track_Filter* this, sample_t out [], int count )
178{ 178{
179 this->emu_time += count; 179 this->emu_time += count;
180 if ( !this->emu_track_ended_ ) 180 if ( !this->emu_track_ended_ )
181 end_track_if_error( this, play_( this->emu_, count, out ) ); 181 end_track_if_error( this, play_( this->emu_, count, out ) );
182 else 182 else
183 memset( out, 0, count * sizeof *out ); 183 memset( out, 0, count * sizeof *out );
184} 184}
185 185
186// number of consecutive silent samples at end 186// number of consecutive silent samples at end
187static int count_silence( sample_t begin [], int size ) 187static int count_silence( sample_t begin [], int size )
188{ 188{
189 sample_t first = *begin; 189 sample_t first = *begin;
190 *begin = silence_threshold * 2; // sentinel 190 *begin = silence_threshold * 2; // sentinel
191 sample_t* p = begin + size; 191 sample_t* p = begin + size;
192 while ( (unsigned) (*--p + silence_threshold) <= (unsigned) silence_threshold * 2 ) { } 192 while ( (unsigned) (*--p + silence_threshold) <= (unsigned) silence_threshold * 2 ) { }
193 *begin = first; 193 *begin = first;
194 return size - (p - begin); 194 return size - (p - begin);
195} 195}
196 196
197// fill internal buffer and check it for silence 197// fill internal buffer and check it for silence
198void fill_buf( struct Track_Filter* this ) 198void fill_buf( struct Track_Filter* this )
199{ 199{
200 assert( !this->buf_remain ); 200 assert( !this->buf_remain );
201 if ( !this->emu_track_ended_ ) 201 if ( !this->emu_track_ended_ )
202 { 202 {
203 emu_play( this, this->buf, buf_size ); 203 emu_play( this, this->buf, buf_size );
204 int silence = count_silence( this->buf, buf_size ); 204 int silence = count_silence( this->buf, buf_size );
205 if ( silence < buf_size ) 205 if ( silence < buf_size )
206 { 206 {
207 this->silence_time = this->emu_time - silence; 207 this->silence_time = this->emu_time - silence;
208 this->buf_remain = buf_size; 208 this->buf_remain = buf_size;
209 return; 209 return;
210 } 210 }
211 } 211 }
212 this->silence_count += buf_size; 212 this->silence_count += buf_size;
213} 213}
214 214
215blargg_err_t track_play( struct Track_Filter* this, int out_count, sample_t out [] ) 215blargg_err_t track_play( struct Track_Filter* this, int out_count, sample_t out [] )
216{ 216{
217 this->emu_error = NULL; 217 this->emu_error = NULL;
218 if ( this->track_ended_ ) 218 if ( this->track_ended_ )
219 { 219 {
220 memset( out, 0, out_count * sizeof *out ); 220 memset( out, 0, out_count * sizeof *out );
221 } 221 }
222 else 222 else
223 { 223 {
224 assert( this->emu_time >= this->out_time ); 224 assert( this->emu_time >= this->out_time );
225 225
226 // prints nifty graph of how far ahead we are when searching for silence 226 // prints nifty graph of how far ahead we are when searching for silence
227 //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / 44100), "*" ); 227 //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / 44100), "*" );
228 228
229 // use any remaining silence samples 229 // use any remaining silence samples
230 int pos = 0; 230 int pos = 0;
231 if ( this->silence_count ) 231 if ( this->silence_count )
232 { 232 {
233 if ( !this->silence_ignored_ ) 233 if ( !this->silence_ignored_ )
234 { 234 {
235 // during a run of silence, run emulator at >=2x speed so it gets ahead 235 // during a run of silence, run emulator at >=2x speed so it gets ahead
236 int ahead_time = this->setup_.lookahead * (this->out_time + out_count - this->silence_time) + 236 int ahead_time = this->setup_.lookahead * (this->out_time + out_count - this->silence_time) +
237 this->silence_time; 237 this->silence_time;
238 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) ) 238 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
239 fill_buf( this ); 239 fill_buf( this );
240 240
241 // end track if sufficient silence has been found 241 // end track if sufficient silence has been found
242 if ( this->emu_time - this->silence_time > this->setup_.max_silence ) 242 if ( this->emu_time - this->silence_time > this->setup_.max_silence )
243 { 243 {
244 this->track_ended_ = this->emu_track_ended_ = true; 244 this->track_ended_ = this->emu_track_ended_ = true;
245 this->silence_count = out_count; 245 this->silence_count = out_count;
246 this->buf_remain = 0; 246 this->buf_remain = 0;
247 } 247 }
248 } 248 }
249 249
250 // fill from remaining silence 250 // fill from remaining silence
251 pos = min( this->silence_count, out_count ); 251 pos = min( this->silence_count, out_count );
252 memset( out, 0, pos * sizeof *out ); 252 memset( out, 0, pos * sizeof *out );
253 this->silence_count -= pos; 253 this->silence_count -= pos;
254 } 254 }
255 255
256 // use any remaining samples from buffer 256 // use any remaining samples from buffer
257 if ( this->buf_remain ) 257 if ( this->buf_remain )
258 { 258 {
259 int n = min( this->buf_remain, (int) (out_count - pos) ); 259 int n = min( this->buf_remain, (int) (out_count - pos) );
260 memcpy( out + pos, this->buf + (buf_size - this->buf_remain), n * sizeof *out ); 260 memcpy( out + pos, this->buf + (buf_size - this->buf_remain), n * sizeof *out );
261 this->buf_remain -= n; 261 this->buf_remain -= n;
262 pos += n; 262 pos += n;
263 } 263 }
264 264
265 // generate remaining samples normally 265 // generate remaining samples normally
266 int remain = out_count - pos; 266 int remain = out_count - pos;
267 if ( remain ) 267 if ( remain )
268 { 268 {
269 emu_play( this, out + pos, remain ); 269 emu_play( this, out + pos, remain );
270 this->track_ended_ |= this->emu_track_ended_; 270 this->track_ended_ |= this->emu_track_ended_;
271 271
272 if ( this->silence_ignored_ && !is_fading( this ) ) 272 if ( this->silence_ignored_ && !is_fading( this ) )
273 { 273 {
274 // if left unupdated, ahead_time could become too large 274 // if left unupdated, ahead_time could become too large
275 this->silence_time = this->emu_time; 275 this->silence_time = this->emu_time;
276 } 276 }
277 else 277 else
278 { 278 {
279 // check end for a new run of silence 279 // check end for a new run of silence
280 int silence = count_silence( out + pos, remain ); 280 int silence = count_silence( out + pos, remain );
281 if ( silence < remain ) 281 if ( silence < remain )
282 this->silence_time = this->emu_time - silence; 282 this->silence_time = this->emu_time - silence;
283 283
284 if ( this->emu_time - this->silence_time >= buf_size ) 284 if ( this->emu_time - this->silence_time >= buf_size )
285 fill_buf( this ); // cause silence detection on next play() 285 fill_buf( this ); // cause silence detection on next play()
286 } 286 }
287 } 287 }
288 288
289 if ( is_fading( this ) ) 289 if ( is_fading( this ) )
290 handle_fade( this, out, out_count ); 290 handle_fade( this, out, out_count );
291 } 291 }
292 this->out_time += out_count; 292 this->out_time += out_count;
293 return this->emu_error; 293 return this->emu_error;
294} 294}