comparison Plugins/Input/console/Spc_Emu.cxx @ 1691:e24213152357 trunk

[svn] .cpp -> .cxx This has the nice side effect that we don't need to add .cpp to .SUFFIXES for OpenBSD.
author js
date Thu, 14 Sep 2006 13:33:10 -0700
parents Plugins/Input/console/Spc_Emu.cpp@705d4c089fce
children
comparison
equal deleted inserted replaced
1690:bb1323938306 1691:e24213152357
1
2 // Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
3
4 #include "Spc_Emu.h"
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include "blargg_endian.h"
9
10 /* Copyright (C) 2004-2006 Shay Green. This module is free software; you
11 can redistribute it and/or modify it under the terms of the GNU Lesser
12 General Public License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version. This
14 module is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
17 more details. You should have received a copy of the GNU Lesser General
18 Public License along with this module; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
20
21 #include BLARGG_SOURCE_BEGIN
22
23 Spc_Emu::Spc_Emu( double gain )
24 {
25 apu.set_gain( gain );
26 }
27
28 Spc_Emu::~Spc_Emu()
29 {
30 }
31
32 const char** Spc_Emu::voice_names() const
33 {
34 static const char* names [] = {
35 "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
36 };
37 return names;
38 }
39
40 void Spc_Emu::mute_voices( int m )
41 {
42 Music_Emu::mute_voices( m );
43 apu.mute_voices( m );
44 }
45
46 blargg_err_t Spc_Emu::set_sample_rate( long sample_rate )
47 {
48 if ( sample_rate != native_sample_rate )
49 {
50 BLARGG_RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
51 resampler.time_ratio( (double) native_sample_rate / sample_rate, 0.9965 );
52 }
53 return Music_Emu::set_sample_rate( sample_rate );
54 }
55
56 blargg_err_t Spc_Emu::load( Data_Reader& in )
57 {
58 header_t h;
59 BLARGG_RETURN_ERR( in.read( &h, sizeof h ) );
60 return load( h, in );
61 }
62
63 blargg_err_t Spc_Emu::load( const header_t& h, Data_Reader& in )
64 {
65 if ( in.remain() < Snes_Spc::spc_file_size - (int) sizeof h )
66 return "Not an SPC file";
67
68 if ( strncmp( h.tag, "SNES-SPC700 Sound File Data", 27 ) != 0 )
69 return "Not an SPC file";
70
71 long remain = in.remain();
72 long size = remain + sizeof h;
73 if ( size < trailer_offset )
74 size = trailer_offset;
75 BLARGG_RETURN_ERR( spc_data.resize( size ) );
76
77 set_track_count( 1 );
78 set_voice_count( Snes_Spc::voice_count );
79
80 memcpy( spc_data.begin(), &h, sizeof h );
81 return in.read( &spc_data [sizeof h], remain );
82 }
83
84 void Spc_Emu::start_track( int track )
85 {
86 Music_Emu::start_track( track );
87
88 resampler.clear();
89 if ( apu.load_spc( spc_data.begin(), spc_data.size() ) )
90 check( false );
91 }
92
93 void Spc_Emu::skip( long count )
94 {
95 count = long (count * resampler.ratio()) & ~1;
96
97 count -= resampler.skip_input( count );
98 if ( count > 0 )
99 apu.skip( count );
100
101 // eliminate pop due to resampler
102 const int resampler_latency = 64;
103 sample_t buf [resampler_latency];
104 play( resampler_latency, buf );
105 }
106
107 void Spc_Emu::play( long count, sample_t* out )
108 {
109 require( track_count() ); // file must be loaded
110
111 if ( sample_rate() == native_sample_rate )
112 {
113 if ( apu.play( count, out ) )
114 log_error();
115 return;
116 }
117
118 long remain = count;
119 while ( remain > 0 )
120 {
121 remain -= resampler.read( &out [count - remain], remain );
122 if ( remain > 0 )
123 {
124 long n = resampler.max_write();
125 if ( apu.play( n, resampler.buffer() ) )
126 log_error();
127 resampler.write( n );
128 }
129 }
130
131 assert( remain == 0 );
132 }
133