1 // Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
2
3 #include "Dual_Resampler.h"
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
9 can redistribute it and/or modify it under the terms of the GNU Lesser
10 General Public License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version. This
12 module is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 details. You should have received a copy of the GNU Lesser General Public
16 License along with this module; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19 #include "blargg_source.h"
20
21 unsigned const resampler_extra = 256;
22
Dual_Resampler()23 Dual_Resampler::Dual_Resampler() :
24 sample_buf_size(0),
25 oversamples_per_frame(-1),
26 buf_pos(-1),
27 resampler_size(0)
28 {
29 }
30
~Dual_Resampler()31 Dual_Resampler::~Dual_Resampler() { }
32
reset(int pairs)33 blargg_err_t Dual_Resampler::reset( int pairs )
34 {
35 // expand allocations a bit
36 RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) );
37 resize( pairs );
38 resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2);
39 return resampler.buffer_size( resampler_size );
40 }
41
resize(int pairs)42 void Dual_Resampler::resize( int pairs )
43 {
44 int new_sample_buf_size = pairs * 2;
45 if ( sample_buf_size != new_sample_buf_size )
46 {
47 if ( (unsigned) new_sample_buf_size > sample_buf.size() )
48 {
49 check( false );
50 return;
51 }
52 sample_buf_size = new_sample_buf_size;
53 oversamples_per_frame = int (pairs * resampler.ratio()) * 2 + 2;
54 clear();
55 }
56 }
57
play_frame_(Blip_Buffer & blip_buf,dsample_t * out)58 void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out )
59 {
60 long pair_count = sample_buf_size >> 1;
61 blip_time_t blip_time = blip_buf.count_clocks( pair_count );
62 int sample_count = oversamples_per_frame - resampler.written();
63
64 int new_count = play_frame( blip_time, sample_count, resampler.buffer() );
65 assert( new_count < resampler_size );
66
67 blip_buf.end_frame( blip_time );
68 assert( blip_buf.samples_avail() == pair_count );
69
70 resampler.write( new_count );
71
72 long count = resampler.read( sample_buf.begin(), sample_buf_size );
73 assert( count == (long) sample_buf_size );
74
75 mix_samples( blip_buf, out );
76 blip_buf.remove_samples( pair_count );
77 }
78
dual_play(long count,dsample_t * out,Blip_Buffer & blip_buf)79 void Dual_Resampler::dual_play( long count, dsample_t* out, Blip_Buffer& blip_buf )
80 {
81 // empty extra buffer
82 long remain = sample_buf_size - buf_pos;
83 if ( remain )
84 {
85 if ( remain > count )
86 remain = count;
87 count -= remain;
88 memcpy( out, &sample_buf [buf_pos], remain * sizeof *out );
89 out += remain;
90 buf_pos += remain;
91 }
92
93 // entire frames
94 while ( count >= (long) sample_buf_size )
95 {
96 play_frame_( blip_buf, out );
97 out += sample_buf_size;
98 count -= sample_buf_size;
99 }
100
101 // extra
102 if ( count )
103 {
104 play_frame_( blip_buf, sample_buf.begin() );
105 buf_pos = count;
106 memcpy( out, sample_buf.begin(), count * sizeof *out );
107 out += count;
108 }
109 }
110
mix_samples(Blip_Buffer & blip_buf,dsample_t * out)111 void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out )
112 {
113 Blip_Reader sn;
114 int bass = sn.begin( blip_buf );
115 const dsample_t* in = sample_buf.begin();
116
117 for ( int n = sample_buf_size >> 1; n--; )
118 {
119 int s = sn.read();
120 blargg_long l = (blargg_long) in [0] * 2 + s;
121 if ( (BOOST::int16_t) l != l )
122 l = 0x7FFF - (l >> 24);
123
124 sn.next( bass );
125 blargg_long r = (blargg_long) in [1] * 2 + s;
126 if ( (BOOST::int16_t) r != r )
127 r = 0x7FFF - (r >> 24);
128
129 in += 2;
130 out [0] = l;
131 out [1] = r;
132 out += 2;
133 }
134
135 sn.end( blip_buf );
136 }
137
138