Mercurial > audlegacy
comparison Plugins/Input/console/Track_Emu.cpp @ 493:c04dff121e1d trunk
[svn] hostile merge, phase 2: reimport based on new plugin code
| author | nenolod |
|---|---|
| date | Tue, 24 Jan 2006 20:19:01 -0800 |
| parents | |
| children | a371216b5c8a |
comparison
equal
deleted
inserted
replaced
| 492:ccb68bad47b2 | 493:c04dff121e1d |
|---|---|
| 1 | |
| 2 // Game_Music_Emu 0.3.0. http://www.slack.net/~ant/ | |
| 3 | |
| 4 #include "Track_Emu.h" | |
| 5 | |
| 6 #include <string.h> | |
| 7 #include <math.h> | |
| 8 | |
| 9 /* Copyright (C) 2005-2006 Shay Green. This module is free software; you | |
| 10 can redistribute it and/or modify it under the terms of the GNU Lesser | |
| 11 General Public License as published by the Free Software Foundation; either | |
| 12 version 2.1 of the License, or (at your option) any later version. This | |
| 13 module is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for | |
| 16 more details. You should have received a copy of the GNU Lesser General | |
| 17 Public License along with this module; if not, write to the Free Software | |
| 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | |
| 19 | |
| 20 #include BLARGG_SOURCE_BEGIN | |
| 21 | |
| 22 int const stereo = 2; // channels for a stereo signal | |
| 23 int const fade_block_size = 512; | |
| 24 int const fade_length = 8000; // msec | |
| 25 int const silence_max = 6; // seconds | |
| 26 int const silence_threshold = 0x10; | |
| 27 | |
| 28 long Track_Emu::msec_to_samples( long msec ) const | |
| 29 { | |
| 30 long rate = emu->sample_rate() * stereo; | |
| 31 return (msec / 1000L) * rate + (msec % 1000L) * rate / 1000; | |
| 32 } | |
| 33 | |
| 34 void Track_Emu::sync( long time ) | |
| 35 { | |
| 36 buf_count = 0; | |
| 37 silence_count = 0; | |
| 38 emu_time = time; | |
| 39 out_time = time; | |
| 40 silence_time = time; | |
| 41 track_ended = time > fade_time + fade_length * stereo * emu->sample_rate(); | |
| 42 } | |
| 43 | |
| 44 void Track_Emu::restart_track() | |
| 45 { | |
| 46 emu->start_track( track ); | |
| 47 emu_time = 0; | |
| 48 | |
| 49 // skip initial silence | |
| 50 for ( int n = 40 * stereo * emu->sample_rate() / buf_size; n--; ) | |
| 51 { | |
| 52 fill_buf( true ); | |
| 53 if ( buf_count || track_ended ) | |
| 54 break; | |
| 55 } | |
| 56 sync( 0 ); | |
| 57 } | |
| 58 | |
| 59 void Track_Emu::seek( long time ) | |
| 60 { | |
| 61 long pos = msec_to_samples( time ) & ~1; | |
| 62 if ( pos < out_time ) | |
| 63 restart_track(); | |
| 64 emu->skip( pos - emu_time ); | |
| 65 sync( pos ); | |
| 66 } | |
| 67 | |
| 68 void Track_Emu::start_track( Music_Emu* e, int t, long length, bool ds ) | |
| 69 { | |
| 70 // to do: remove | |
| 71 //length = 50 * 1000; | |
| 72 //ds = true; | |
| 73 //t = 23; | |
| 74 | |
| 75 emu = e; | |
| 76 track = t; | |
| 77 detect_silence = ds; | |
| 78 fade_factor = pow( 0.005, 1.0 / msec_to_samples( fade_length ) ); | |
| 79 fade_time = msec_to_samples( length ); | |
| 80 restart_track(); | |
| 81 } | |
| 82 | |
| 83 static bool is_silence( const Music_Emu::sample_t* p, int count ) | |
| 84 { | |
| 85 while ( count-- ) | |
| 86 { | |
| 87 if ( (unsigned) (*p++ + silence_threshold / 2) > (unsigned) silence_threshold ) | |
| 88 return false; | |
| 89 } | |
| 90 return true; | |
| 91 } | |
| 92 | |
| 93 void Track_Emu::fill_buf( bool check_silence ) | |
| 94 { | |
| 95 if ( !buf_count && !track_ended && | |
| 96 emu_time - out_time < silence_max * stereo * emu->sample_rate() ) | |
| 97 { | |
| 98 emu->play( buf_size, buf ); | |
| 99 emu_time += buf_size; | |
| 100 if ( (check_silence || emu_time > fade_time) && is_silence( buf, buf_size ) ) | |
| 101 { | |
| 102 silence_count += buf_size; | |
| 103 } | |
| 104 else | |
| 105 { | |
| 106 silence_time = emu_time; | |
| 107 buf_count = buf_size; | |
| 108 } | |
| 109 if ( emu->track_ended() || emu->error_count() ) | |
| 110 track_ended = true; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 inline void Track_Emu::end_track() | |
| 115 { | |
| 116 silence_count = 0; | |
| 117 buf_count = 0; | |
| 118 track_ended = true; | |
| 119 } | |
| 120 | |
| 121 bool Track_Emu::play( int out_count, Music_Emu::sample_t* out ) | |
| 122 { | |
| 123 assert( out_count % 2 == 0 ); | |
| 124 assert( emu ); | |
| 125 | |
| 126 int pos = 0; | |
| 127 while ( pos < out_count ) | |
| 128 { | |
| 129 // fill with any remaining silence | |
| 130 int count = min( silence_count, out_count - pos ); | |
| 131 if ( count ) | |
| 132 { | |
| 133 silence_count -= count; | |
| 134 memset( &out [pos], 0, count * sizeof *out ); | |
| 135 } | |
| 136 else | |
| 137 { | |
| 138 // empty internal buffer | |
| 139 count = min( buf_count, out_count - pos ); | |
| 140 if ( !count && track_ended ) | |
| 141 { | |
| 142 memset( &out [pos], 0, (out_count - pos) * sizeof *out ); | |
| 143 return true; | |
| 144 } | |
| 145 | |
| 146 memcpy( &out [pos], &buf [buf_size - buf_count], count * sizeof *out ); | |
| 147 buf_count -= count; | |
| 148 } | |
| 149 pos += count; | |
| 150 | |
| 151 // keep internal buffer full and possibly run ahead | |
| 152 for ( int n = 6; n--; ) | |
| 153 fill_buf( detect_silence ); | |
| 154 } | |
| 155 out_time += out_count; | |
| 156 | |
| 157 if ( emu_time - silence_time > silence_max * stereo * emu->sample_rate() && silence_time ) | |
| 158 end_track(); | |
| 159 | |
| 160 // fade if track is ending | |
| 161 if ( out_time > fade_time ) | |
| 162 { | |
| 163 for ( int i = 0; i < out_count; i += fade_block_size ) | |
| 164 { | |
| 165 double gain = pow( fade_factor, (double) (out_time + i - fade_time) ); | |
| 166 if ( gain < 0.005 ) | |
| 167 end_track(); | |
| 168 | |
| 169 int count = min( fade_block_size, out_count - i ); | |
| 170 int igain = gain * (1 << 15); | |
| 171 for ( int j = 0; j < count; j++ ) | |
| 172 out [i + j] = (out [i + j] * igain) >> 15; | |
| 173 } | |
| 174 } | |
| 175 | |
| 176 return !silence_count && !buf_count && track_ended; | |
| 177 } | |
| 178 |
