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