/src/vlc/contrib/contrib-build/game-music-emu/gme/Classic_Emu.cpp
Line | Count | Source |
1 | | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ |
2 | | |
3 | | #include "Classic_Emu.h" |
4 | | |
5 | | #include "Multi_Buffer.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 | | Classic_Emu::Classic_Emu() |
22 | 2.18k | { |
23 | 2.18k | buf = 0; |
24 | 2.18k | stereo_buffer = 0; |
25 | 2.18k | voice_types = 0; |
26 | | |
27 | | // avoid inconsistency in our duplicated constants |
28 | 2.18k | blaarg_static_assert( (int) wave_type == (int) Multi_Buffer::wave_type, "wave_type inconsistent across two classes using it" ); |
29 | 2.18k | blaarg_static_assert( (int) noise_type == (int) Multi_Buffer::noise_type, "noise_type inconsistent across two classes using it" ); |
30 | 2.18k | blaarg_static_assert( (int) mixed_type == (int) Multi_Buffer::mixed_type, "mixed_type inconsistent across two classes using it" ); |
31 | 2.18k | } |
32 | | |
33 | | Classic_Emu::~Classic_Emu() |
34 | 2.18k | { |
35 | 2.18k | delete stereo_buffer; |
36 | 2.18k | } |
37 | | |
38 | | void Classic_Emu::set_equalizer_( equalizer_t const& eq ) |
39 | 4.35k | { |
40 | 4.35k | Music_Emu::set_equalizer_( eq ); |
41 | 4.35k | update_eq( eq.treble ); |
42 | 4.35k | if ( buf ) |
43 | 2.20k | buf->bass_freq( (int) equalizer().bass ); |
44 | 4.35k | } |
45 | | |
46 | | blargg_err_t Classic_Emu::set_sample_rate_( long rate ) |
47 | 2.18k | { |
48 | 2.18k | if ( !buf ) |
49 | 0 | { |
50 | 0 | if ( !stereo_buffer ) |
51 | 0 | CHECK_ALLOC( stereo_buffer = BLARGG_NEW Stereo_Buffer ); |
52 | 0 | buf = stereo_buffer; |
53 | 0 | } |
54 | 2.18k | return buf->set_sample_rate( rate, 1000 / 20 ); |
55 | 2.18k | } |
56 | | |
57 | | blargg_err_t Classic_Emu::set_multi_channel ( bool is_enabled ) |
58 | 2.09k | { |
59 | 2.09k | RETURN_ERR( Music_Emu::set_multi_channel_( is_enabled ) ); |
60 | 2.09k | return 0; |
61 | 2.09k | } |
62 | | |
63 | | void Classic_Emu::mute_voices_( int mask ) |
64 | 2.12k | { |
65 | 2.12k | Music_Emu::mute_voices_( mask ); |
66 | 16.3k | for ( int i = voice_count(); i--; ) |
67 | 14.1k | { |
68 | 14.1k | if ( mask & (1 << i) ) |
69 | 0 | { |
70 | 0 | set_voice( i, 0, 0, 0 ); |
71 | 0 | } |
72 | 14.1k | else |
73 | 14.1k | { |
74 | 14.1k | Multi_Buffer::channel_t ch = buf->channel( i, (voice_types ? voice_types [i] : 0) ); |
75 | 14.1k | assert( (ch.center && ch.left && ch.right) || |
76 | 14.1k | (!ch.center && !ch.left && !ch.right) ); // all or nothing |
77 | 14.1k | set_voice( i, ch.center, ch.left, ch.right ); |
78 | 14.1k | } |
79 | 14.1k | } |
80 | 2.12k | } |
81 | | |
82 | | void Classic_Emu::change_clock_rate( uint32_t rate ) |
83 | 2.20k | { |
84 | 2.20k | clock_rate_ = rate; |
85 | 2.20k | buf->clock_rate( rate ); |
86 | 2.20k | } |
87 | | |
88 | | blargg_err_t Classic_Emu::setup_buffer( uint32_t rate ) |
89 | 2.20k | { |
90 | 2.20k | change_clock_rate( rate ); |
91 | 2.20k | RETURN_ERR( buf->set_channel_count( voice_count() ) ); |
92 | 2.20k | set_equalizer( equalizer() ); |
93 | 2.20k | buf_changed_count = buf->channels_changed_count(); |
94 | 2.20k | return 0; |
95 | 2.20k | } |
96 | | |
97 | | blargg_err_t Classic_Emu::start_track_( int track ) |
98 | 9.85k | { |
99 | 9.85k | RETURN_ERR( Music_Emu::start_track_( track ) ); |
100 | 9.85k | buf->clear(); |
101 | 9.85k | return 0; |
102 | 9.85k | } |
103 | | |
104 | | blargg_err_t Classic_Emu::play_( long count, sample_t* out ) |
105 | 3.88M | { |
106 | 3.88M | long remain = count; |
107 | 9.45M | while ( remain ) |
108 | 5.57M | { |
109 | 5.57M | remain -= buf->read_samples( &out [count - remain], remain ); |
110 | 5.57M | if ( remain ) |
111 | 1.68M | { |
112 | 1.68M | if ( buf_changed_count != buf->channels_changed_count() ) |
113 | 0 | { |
114 | 0 | buf_changed_count = buf->channels_changed_count(); |
115 | 0 | remute_voices(); |
116 | 0 | } |
117 | 1.68M | int msec = buf->length(); |
118 | 1.68M | blip_time_t clocks_emulated = (int32_t) msec * clock_rate_ / 1000; |
119 | 1.68M | RETURN_ERR( run_clocks( clocks_emulated, msec ) ); |
120 | 1.68M | assert( clocks_emulated ); |
121 | 1.68M | buf->end_frame( clocks_emulated ); |
122 | 1.68M | } |
123 | 5.57M | } |
124 | 3.88M | return 0; |
125 | 3.88M | } |
126 | | |
127 | | // Rom_Data |
128 | | |
129 | | blargg_err_t Rom_Data_::load_rom_data_( Data_Reader& in, |
130 | | int header_size, void* header_out, int fill, long pad_size ) |
131 | 2.06k | { |
132 | 2.06k | long file_offset = pad_size - header_size; |
133 | | |
134 | 2.06k | rom_addr = 0; |
135 | 2.06k | mask = 0; |
136 | 2.06k | size_ = 0; |
137 | 2.06k | rom.clear(); |
138 | | |
139 | 2.06k | file_size_ = in.remain(); |
140 | 2.06k | if ( file_size_ <= header_size ) // <= because there must be data after header |
141 | 8 | return gme_wrong_file_type; |
142 | 2.06k | blargg_err_t err = rom.resize( file_offset + file_size_ + pad_size ); |
143 | 2.06k | if ( !err ) |
144 | 2.06k | err = in.read( rom.begin() + file_offset, file_size_ ); |
145 | 2.06k | if ( err ) |
146 | 0 | { |
147 | 0 | rom.clear(); |
148 | 0 | return err; |
149 | 0 | } |
150 | | |
151 | 2.06k | file_size_ -= header_size; |
152 | 2.06k | memcpy( header_out, &rom [file_offset], header_size ); |
153 | | |
154 | 2.06k | memset( rom.begin() , fill, pad_size ); |
155 | 2.06k | memset( rom.end() - pad_size, fill, pad_size ); |
156 | | |
157 | 2.06k | return 0; |
158 | 2.06k | } |
159 | | |
160 | | void Rom_Data_::set_addr_( long addr, int unit ) |
161 | 4.57k | { |
162 | 4.57k | rom_addr = addr - unit - pad_extra; |
163 | | |
164 | 4.57k | long rounded = (addr + file_size_ + unit - 1) / unit * unit; |
165 | 4.57k | if ( rounded <= 0 ) |
166 | 1.28k | { |
167 | 1.28k | rounded = 0; |
168 | 1.28k | } |
169 | 3.29k | else |
170 | 3.29k | { |
171 | 3.29k | int shift = 0; |
172 | 3.29k | unsigned long max_addr = (unsigned long) (rounded - 1); |
173 | 46.8k | while ( max_addr >> shift ) |
174 | 43.5k | shift++; |
175 | 3.29k | mask = (1L << shift) - 1; |
176 | 3.29k | } |
177 | | |
178 | 4.57k | if ( addr < 0 ) |
179 | 1.28k | addr = 0; |
180 | 4.57k | size_ = rounded; |
181 | 4.57k | if ( rom.resize( rounded - rom_addr + pad_extra ) ) { } // OK if shrink fails |
182 | | |
183 | 4.57k | if ( 0 ) |
184 | 0 | { |
185 | 0 | debug_printf( "addr: %X\n", (int)addr ); |
186 | 0 | debug_printf( "file_size: %ld\n", file_size_ ); |
187 | 0 | debug_printf( "rounded: %ld\n", rounded ); |
188 | 0 | debug_printf( "mask: $%X\n", mask ); |
189 | 0 | } |
190 | 4.57k | } |