diff options
author | Björn Stenberg <bjorn@haxx.se> | 2008-11-05 13:30:58 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2008-11-05 13:30:58 +0000 |
commit | 45bd7e024603ba47207e5cc64c61e4116e8f1261 (patch) | |
tree | cf789bb0ce99eb8b153c5445c535ef5c4e4ead62 /apps/codecs/spc/spc_codec.h | |
parent | 7ec9ceeaaabb75adaa790b41eba6dec020232fa6 (diff) | |
download | rockbox-45bd7e024603ba47207e5cc64c61e4116e8f1261.tar.gz rockbox-45bd7e024603ba47207e5cc64c61e4116e8f1261.zip |
Codec lib directories renamed, except for demac.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19018 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/spc/spc_codec.h')
-rw-r--r-- | apps/codecs/spc/spc_codec.h | 454 |
1 files changed, 0 insertions, 454 deletions
diff --git a/apps/codecs/spc/spc_codec.h b/apps/codecs/spc/spc_codec.h deleted file mode 100644 index 33e566aea2..0000000000 --- a/apps/codecs/spc/spc_codec.h +++ /dev/null | |||
@@ -1,454 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007-2008 Michael Sevakis (jhMikeS) | ||
11 | * Copyright (C) 2006-2007 Adam Gashlin (hcs) | ||
12 | * Copyright (C) 2004-2007 Shay Green (blargg) | ||
13 | * Copyright (C) 2002 Brad Martin | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation; either version 2 | ||
18 | * of the License, or (at your option) any later version. | ||
19 | * | ||
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
21 | * KIND, either express or implied. | ||
22 | * | ||
23 | ****************************************************************************/ | ||
24 | |||
25 | /* lovingly ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */ | ||
26 | /* DSP Based on Brad Martin's OpenSPC DSP emulator */ | ||
27 | /* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */ | ||
28 | |||
29 | #ifndef _SPC_CODEC_H_ | ||
30 | #define _SPC_CODEC_H_ | ||
31 | |||
32 | /* rather than comment out asserts, just define NDEBUG */ | ||
33 | #define NDEBUG | ||
34 | #include <assert.h> | ||
35 | |||
36 | /** Basic configuration options **/ | ||
37 | |||
38 | #define SPC_DUAL_CORE 1 | ||
39 | |||
40 | #if !defined(SPC_DUAL_CORE) || NUM_CORES == 1 | ||
41 | #undef SPC_DUAL_CORE | ||
42 | #define SPC_DUAL_CORE 0 | ||
43 | #endif | ||
44 | |||
45 | /* TGB is the only target fast enough for gaussian and realtime BRR decode */ | ||
46 | /* echo is almost fast enough but not quite */ | ||
47 | #if defined(TOSHIBA_GIGABEAT_F) || defined(TOSHIBA_GIGABEAT_S) ||\ | ||
48 | defined(SIMULATOR) | ||
49 | /* Don't cache BRR waves */ | ||
50 | #define SPC_BRRCACHE 0 | ||
51 | |||
52 | /* Allow gaussian interpolation */ | ||
53 | #define SPC_NOINTERP 0 | ||
54 | |||
55 | /* Allow echo processing */ | ||
56 | #define SPC_NOECHO 0 | ||
57 | #elif defined(CPU_COLDFIRE) | ||
58 | /* Cache BRR waves */ | ||
59 | #define SPC_BRRCACHE 1 | ||
60 | |||
61 | /* Disable gaussian interpolation */ | ||
62 | #define SPC_NOINTERP 1 | ||
63 | |||
64 | /* Allow echo processing */ | ||
65 | #define SPC_NOECHO 0 | ||
66 | #elif defined (CPU_PP) && SPC_DUAL_CORE | ||
67 | /* Cache BRR waves */ | ||
68 | #define SPC_BRRCACHE 1 | ||
69 | |||
70 | /* Disable gaussian interpolation */ | ||
71 | #define SPC_NOINTERP 1 | ||
72 | |||
73 | /* Allow echo processing */ | ||
74 | #define SPC_NOECHO 0 | ||
75 | #else | ||
76 | /* Cache BRR waves */ | ||
77 | #define SPC_BRRCACHE 1 | ||
78 | |||
79 | /* Disable gaussian interpolation */ | ||
80 | #define SPC_NOINTERP 1 | ||
81 | |||
82 | /* Disable echo processing */ | ||
83 | #define SPC_NOECHO 1 | ||
84 | #endif | ||
85 | |||
86 | #ifdef CPU_ARM | ||
87 | |||
88 | #if CONFIG_CPU != PP5002 | ||
89 | #undef ICODE_ATTR | ||
90 | #define ICODE_ATTR | ||
91 | |||
92 | #undef IDATA_ATTR | ||
93 | #define IDATA_ATTR | ||
94 | |||
95 | #undef ICONST_ATTR | ||
96 | #define ICONST_ATTR | ||
97 | |||
98 | #undef IBSS_ATTR | ||
99 | #define IBSS_ATTR | ||
100 | #endif | ||
101 | |||
102 | #if SPC_DUAL_CORE | ||
103 | #undef SHAREDBSS_ATTR | ||
104 | #define SHAREDBSS_ATTR __attribute__ ((section(".ibss"))) | ||
105 | #undef SHAREDDATA_ATTR | ||
106 | #define SHAREDDATA_ATTR __attribute__((section(".idata"))) | ||
107 | #endif | ||
108 | #endif | ||
109 | |||
110 | /* Samples per channel per iteration */ | ||
111 | #if defined(CPU_PP) && NUM_CORES == 1 | ||
112 | #define WAV_CHUNK_SIZE 2048 | ||
113 | #else | ||
114 | #define WAV_CHUNK_SIZE 1024 | ||
115 | #endif | ||
116 | |||
117 | /**************** Little-endian handling ****************/ | ||
118 | |||
119 | static inline unsigned get_le16( void const* p ) | ||
120 | { | ||
121 | return ((unsigned char const*) p) [1] * 0x100u + | ||
122 | ((unsigned char const*) p) [0]; | ||
123 | } | ||
124 | |||
125 | static inline int get_le16s( void const* p ) | ||
126 | { | ||
127 | return ((signed char const*) p) [1] * 0x100 + | ||
128 | ((unsigned char const*) p) [0]; | ||
129 | } | ||
130 | |||
131 | static inline void set_le16( void* p, unsigned n ) | ||
132 | { | ||
133 | ((unsigned char*) p) [1] = (unsigned char) (n >> 8); | ||
134 | ((unsigned char*) p) [0] = (unsigned char) n; | ||
135 | } | ||
136 | |||
137 | #define GET_LE16( addr ) get_le16( addr ) | ||
138 | #define SET_LE16( addr, data ) set_le16( addr, data ) | ||
139 | #define INT16A( addr ) (*(uint16_t*) (addr)) | ||
140 | #define INT16SA( addr ) (*(int16_t*) (addr)) | ||
141 | |||
142 | #ifdef ROCKBOX_LITTLE_ENDIAN | ||
143 | #define GET_LE16A( addr ) (*(uint16_t*) (addr)) | ||
144 | #define GET_LE16SA( addr ) (*( int16_t*) (addr)) | ||
145 | #define SET_LE16A( addr, data ) (void) (*(uint16_t*) (addr) = (data)) | ||
146 | #else | ||
147 | #define GET_LE16A( addr ) get_le16 ( addr ) | ||
148 | #define GET_LE16SA( addr ) get_le16s( addr ) | ||
149 | #define SET_LE16A( addr, data ) set_le16 ( addr, data ) | ||
150 | #endif | ||
151 | |||
152 | struct Spc_Emu; | ||
153 | #define THIS struct Spc_Emu* const this | ||
154 | |||
155 | /* The CPU portion (shock!) */ | ||
156 | |||
157 | struct cpu_regs_t | ||
158 | { | ||
159 | long pc; /* more than 16 bits to allow overflow detection */ | ||
160 | uint8_t a; | ||
161 | uint8_t x; | ||
162 | uint8_t y; | ||
163 | uint8_t status; | ||
164 | uint8_t sp; | ||
165 | }; | ||
166 | |||
167 | struct cpu_ram_t | ||
168 | { | ||
169 | union { | ||
170 | uint8_t padding1 [0x100]; | ||
171 | uint16_t align; | ||
172 | } padding1 [1]; | ||
173 | uint8_t ram [0x10000]; | ||
174 | uint8_t padding2 [0x100]; | ||
175 | }; | ||
176 | |||
177 | #undef RAM | ||
178 | #define RAM ram.ram | ||
179 | extern struct cpu_ram_t ram; | ||
180 | |||
181 | long CPU_run( THIS, long start_time ) ICODE_ATTR; | ||
182 | void CPU_Init( THIS ); | ||
183 | |||
184 | /* The DSP portion (awe!) */ | ||
185 | enum { VOICE_COUNT = 8 }; | ||
186 | enum { REGISTER_COUNT = 128 }; | ||
187 | |||
188 | struct raw_voice_t | ||
189 | { | ||
190 | int8_t volume [2]; | ||
191 | uint8_t rate [2]; | ||
192 | uint8_t waveform; | ||
193 | uint8_t adsr [2]; /* envelope rates for attack, decay, and sustain */ | ||
194 | uint8_t gain; /* envelope gain (if not using ADSR) */ | ||
195 | int8_t envx; /* current envelope level */ | ||
196 | int8_t outx; /* current sample */ | ||
197 | int8_t unused [6]; | ||
198 | }; | ||
199 | |||
200 | struct globals_t | ||
201 | { | ||
202 | int8_t unused1 [12]; | ||
203 | int8_t volume_0; /* 0C Main Volume Left (-.7) */ | ||
204 | int8_t echo_feedback; /* 0D Echo Feedback (-.7) */ | ||
205 | int8_t unused2 [14]; | ||
206 | int8_t volume_1; /* 1C Main Volume Right (-.7) */ | ||
207 | int8_t unused3 [15]; | ||
208 | int8_t echo_volume_0; /* 2C Echo Volume Left (-.7) */ | ||
209 | uint8_t pitch_mods; /* 2D Pitch Modulation on/off for each voice */ | ||
210 | int8_t unused4 [14]; | ||
211 | int8_t echo_volume_1; /* 3C Echo Volume Right (-.7) */ | ||
212 | uint8_t noise_enables; /* 3D Noise output on/off for each voice */ | ||
213 | int8_t unused5 [14]; | ||
214 | uint8_t key_ons; /* 4C Key On for each voice */ | ||
215 | uint8_t echo_ons; /* 4D Echo on/off for each voice */ | ||
216 | int8_t unused6 [14]; | ||
217 | uint8_t key_offs; /* 5C key off for each voice | ||
218 | (instantiates release mode) */ | ||
219 | uint8_t wave_page; /* 5D source directory (wave table offsets) */ | ||
220 | int8_t unused7 [14]; | ||
221 | uint8_t flags; /* 6C flags and noise freq */ | ||
222 | uint8_t echo_page; /* 6D */ | ||
223 | int8_t unused8 [14]; | ||
224 | uint8_t wave_ended; /* 7C */ | ||
225 | uint8_t echo_delay; /* 7D ms >> 4 */ | ||
226 | char unused9 [2]; | ||
227 | }; | ||
228 | |||
229 | enum state_t | ||
230 | { /* -1, 0, +1 allows more efficient if statements */ | ||
231 | state_decay = -1, | ||
232 | state_sustain = 0, | ||
233 | state_attack = +1, | ||
234 | state_release = 2 | ||
235 | }; | ||
236 | |||
237 | struct cache_entry_t | ||
238 | { | ||
239 | int16_t const* samples; | ||
240 | unsigned end; /* past-the-end position */ | ||
241 | unsigned loop; /* number of samples in loop */ | ||
242 | unsigned start_addr; | ||
243 | }; | ||
244 | |||
245 | enum { BRR_BLOCK_SIZE = 16 }; | ||
246 | enum { BRR_CACHE_SIZE = 0x20000 + 32} ; | ||
247 | |||
248 | struct voice_t | ||
249 | { | ||
250 | #if SPC_BRRCACHE | ||
251 | int16_t const* samples; | ||
252 | long wave_end; | ||
253 | int wave_loop; | ||
254 | #else | ||
255 | int16_t samples [3 + BRR_BLOCK_SIZE + 1]; | ||
256 | int block_header; /* header byte from current block */ | ||
257 | #endif | ||
258 | uint8_t const* addr; | ||
259 | short volume [2]; | ||
260 | long position;/* position in samples buffer, with 12-bit fraction */ | ||
261 | short envx; | ||
262 | short env_mode; | ||
263 | short env_timer; | ||
264 | short key_on_delay; | ||
265 | }; | ||
266 | |||
267 | #if SPC_BRRCACHE | ||
268 | /* a little extra for samples that go past end */ | ||
269 | extern int16_t BRRcache [BRR_CACHE_SIZE]; | ||
270 | #endif | ||
271 | |||
272 | enum { FIR_BUF_HALF = 8 }; | ||
273 | |||
274 | #if defined(CPU_COLDFIRE) | ||
275 | /* global because of the large aligment requirement for hardware masking - | ||
276 | * L-R interleaved 16-bit samples for easy loading and mac.w use. | ||
277 | */ | ||
278 | enum | ||
279 | { | ||
280 | FIR_BUF_CNT = FIR_BUF_HALF, | ||
281 | FIR_BUF_SIZE = FIR_BUF_CNT * sizeof ( int32_t ), | ||
282 | FIR_BUF_ALIGN = FIR_BUF_SIZE * 2, | ||
283 | FIR_BUF_MASK = ~((FIR_BUF_ALIGN / 2) | (sizeof ( int32_t ) - 1)) | ||
284 | }; | ||
285 | #elif defined (CPU_ARM) | ||
286 | enum | ||
287 | { | ||
288 | FIR_BUF_CNT = FIR_BUF_HALF * 2 * 2, | ||
289 | FIR_BUF_SIZE = FIR_BUF_CNT * sizeof ( int32_t ), | ||
290 | FIR_BUF_ALIGN = FIR_BUF_SIZE, | ||
291 | FIR_BUF_MASK = ~((FIR_BUF_ALIGN / 2) | (sizeof ( int32_t ) * 2 - 1)) | ||
292 | }; | ||
293 | #endif /* CPU_* */ | ||
294 | |||
295 | struct Spc_Dsp | ||
296 | { | ||
297 | union | ||
298 | { | ||
299 | struct raw_voice_t voice [VOICE_COUNT]; | ||
300 | uint8_t reg [REGISTER_COUNT]; | ||
301 | struct globals_t g; | ||
302 | int16_t align; | ||
303 | } r; | ||
304 | |||
305 | unsigned echo_pos; | ||
306 | int keys_down; | ||
307 | int noise_count; | ||
308 | uint16_t noise; /* also read as int16_t */ | ||
309 | |||
310 | #if defined(CPU_COLDFIRE) | ||
311 | /* circularly hardware masked address */ | ||
312 | int32_t *fir_ptr; | ||
313 | /* wrapped address just behind current position - | ||
314 | allows mac.w to increment and mask fir_ptr */ | ||
315 | int32_t *last_fir_ptr; | ||
316 | /* copy of echo FIR constants as int16_t for use with mac.w */ | ||
317 | int16_t fir_coeff [VOICE_COUNT]; | ||
318 | #elif defined (CPU_ARM) | ||
319 | /* fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code */ | ||
320 | int32_t *fir_ptr; | ||
321 | /* copy of echo FIR constants as int32_t, for faster access */ | ||
322 | int32_t fir_coeff [VOICE_COUNT]; | ||
323 | #else | ||
324 | /* fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code */ | ||
325 | int fir_pos; /* (0 to 7) */ | ||
326 | int fir_buf [FIR_BUF_HALF * 2] [2]; | ||
327 | /* copy of echo FIR constants as int, for faster access */ | ||
328 | int fir_coeff [VOICE_COUNT]; | ||
329 | #endif | ||
330 | |||
331 | struct voice_t voice_state [VOICE_COUNT]; | ||
332 | |||
333 | #if SPC_BRRCACHE | ||
334 | uint8_t oldsize; | ||
335 | struct cache_entry_t wave_entry [256]; | ||
336 | struct cache_entry_t wave_entry_old [256]; | ||
337 | #endif | ||
338 | }; | ||
339 | |||
340 | struct src_dir | ||
341 | { | ||
342 | char start [2]; | ||
343 | char loop [2]; | ||
344 | }; | ||
345 | |||
346 | void DSP_run_( struct Spc_Dsp* this, long count, int32_t* out_buf ) ICODE_ATTR; | ||
347 | void DSP_reset( struct Spc_Dsp* this ); | ||
348 | |||
349 | static inline void DSP_run( struct Spc_Dsp* this, long count, int32_t* out ) | ||
350 | { | ||
351 | /* Should we just fill the buffer with silence? Flags won't be cleared */ | ||
352 | /* during this run so it seems it should keep resetting every sample. */ | ||
353 | if ( this->r.g.flags & 0x80 ) | ||
354 | DSP_reset( this ); | ||
355 | |||
356 | DSP_run_( this, count, out ); | ||
357 | } | ||
358 | |||
359 | /**************** SPC emulator ****************/ | ||
360 | /* 1.024 MHz clock / 32000 samples per second */ | ||
361 | enum { CLOCKS_PER_SAMPLE = 32 }; | ||
362 | |||
363 | enum { EXTRA_CLOCKS = CLOCKS_PER_SAMPLE / 2 }; | ||
364 | |||
365 | /* using this disables timer (since this will always be in the future) */ | ||
366 | enum { TIMER_DISABLED_TIME = 127 }; | ||
367 | |||
368 | enum { ROM_SIZE = 64 }; | ||
369 | enum { ROM_ADDR = 0xFFC0 }; | ||
370 | |||
371 | enum { TIMER_COUNT = 3 }; | ||
372 | |||
373 | struct Timer | ||
374 | { | ||
375 | long next_tick; | ||
376 | int period; | ||
377 | int count; | ||
378 | int shift; | ||
379 | int enabled; | ||
380 | int counter; | ||
381 | }; | ||
382 | |||
383 | void Timer_run_( struct Timer* t, long time ) ICODE_ATTR; | ||
384 | |||
385 | static inline void Timer_run( struct Timer* t, long time ) | ||
386 | { | ||
387 | if ( time >= t->next_tick ) | ||
388 | Timer_run_( t, time ); | ||
389 | } | ||
390 | |||
391 | struct Spc_Emu | ||
392 | { | ||
393 | uint8_t cycle_table [0x100]; | ||
394 | struct cpu_regs_t r; | ||
395 | |||
396 | int32_t* sample_buf; | ||
397 | long next_dsp; | ||
398 | int rom_enabled; | ||
399 | int extra_cycles; | ||
400 | |||
401 | struct Timer timer [TIMER_COUNT]; | ||
402 | |||
403 | /* large objects at end */ | ||
404 | struct Spc_Dsp dsp; | ||
405 | uint8_t extra_ram [ROM_SIZE]; | ||
406 | uint8_t boot_rom [ROM_SIZE]; | ||
407 | }; | ||
408 | |||
409 | enum { SPC_FILE_SIZE = 0x10180 }; | ||
410 | |||
411 | struct spc_file_t | ||
412 | { | ||
413 | char signature [27]; | ||
414 | char unused [10]; | ||
415 | uint8_t pc [2]; | ||
416 | uint8_t a; | ||
417 | uint8_t x; | ||
418 | uint8_t y; | ||
419 | uint8_t status; | ||
420 | uint8_t sp; | ||
421 | char unused2 [212]; | ||
422 | uint8_t ram [0x10000]; | ||
423 | uint8_t dsp [128]; | ||
424 | uint8_t ipl_rom [128]; | ||
425 | }; | ||
426 | |||
427 | void SPC_Init( THIS ); | ||
428 | |||
429 | int SPC_load_spc( THIS, const void* data, long size ); | ||
430 | |||
431 | /**************** DSP interaction ****************/ | ||
432 | void DSP_write( struct Spc_Dsp* this, int i, int data ) ICODE_ATTR; | ||
433 | |||
434 | static inline int DSP_read( struct Spc_Dsp* this, int i ) | ||
435 | { | ||
436 | assert( (unsigned) i < REGISTER_COUNT ); | ||
437 | return this->r.reg [i]; | ||
438 | } | ||
439 | |||
440 | void SPC_run_dsp_( THIS, long time ) ICODE_ATTR; | ||
441 | |||
442 | static inline void SPC_run_dsp( THIS, long time ) | ||
443 | { | ||
444 | if ( time >= this->next_dsp ) | ||
445 | SPC_run_dsp_( this, time ); | ||
446 | } | ||
447 | |||
448 | int SPC_read( THIS, unsigned addr, long const time ) ICODE_ATTR; | ||
449 | void SPC_write( THIS, unsigned addr, int data, long const time ) ICODE_ATTR; | ||
450 | |||
451 | /**************** Sample generation ****************/ | ||
452 | int SPC_play( THIS, long count, int32_t* out ) ICODE_ATTR; | ||
453 | |||
454 | #endif /* _SPC_CODEC_H_ */ | ||