Improved bitrev with approach suggested by Jens Arnold, gives 0.5%-1% speedup for...
[kugel-rb.git] / apps / codecs / libspc / spc_codec.h
blobcf72f90af4a6e0221bfd51e20f368a18857ea657
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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
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.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
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 */
29 #ifndef _SPC_CODEC_H_
30 #define _SPC_CODEC_H_
32 /* rather than comment out asserts, just define NDEBUG */
33 #ifndef NDEBUG
34 #define NDEBUG
35 #endif
36 #include <assert.h>
38 /** Basic configuration options **/
40 #define SPC_DUAL_CORE 1
42 #if !defined(SPC_DUAL_CORE) || NUM_CORES == 1
43 #undef SPC_DUAL_CORE
44 #define SPC_DUAL_CORE 0
45 #endif
47 /* TGB is the only target fast enough for gaussian and realtime BRR decode */
48 /* echo is almost fast enough but not quite */
49 #if defined(TOSHIBA_GIGABEAT_F) || defined(TOSHIBA_GIGABEAT_S) ||\
50 defined(SIMULATOR) || MEMORYSIZE <= 2
51 /* Don't cache BRR waves */
52 #define SPC_BRRCACHE 0
54 /* Allow gaussian interpolation */
55 #define SPC_NOINTERP 0
57 /* Allow echo processing */
58 #define SPC_NOECHO 0
59 #elif defined(CPU_COLDFIRE)
60 /* Cache BRR waves */
61 #define SPC_BRRCACHE 1
63 /* Disable gaussian interpolation */
64 #define SPC_NOINTERP 1
66 /* Allow echo processing */
67 #define SPC_NOECHO 0
68 #elif defined (CPU_PP) && SPC_DUAL_CORE
69 /* Cache BRR waves */
70 #define SPC_BRRCACHE 1
72 /* Disable gaussian interpolation */
73 #define SPC_NOINTERP 1
75 /* Allow echo processing */
76 #define SPC_NOECHO 0
77 #else
78 /* Cache BRR waves */
79 #define SPC_BRRCACHE 1
81 /* Disable gaussian interpolation */
82 #define SPC_NOINTERP 1
84 /* Disable echo processing */
85 #define SPC_NOECHO 1
86 #endif
88 #ifdef CPU_ARM
90 #if CONFIG_CPU != PP5002
91 #undef ICODE_ATTR
92 #define ICODE_ATTR
94 #undef IDATA_ATTR
95 #define IDATA_ATTR
97 #undef ICONST_ATTR
98 #define ICONST_ATTR
100 #undef IBSS_ATTR
101 #define IBSS_ATTR
102 #endif
104 #if SPC_DUAL_CORE
105 #undef SHAREDBSS_ATTR
106 #define SHAREDBSS_ATTR __attribute__ ((section(".ibss")))
107 #undef SHAREDDATA_ATTR
108 #define SHAREDDATA_ATTR __attribute__((section(".idata")))
109 #endif
110 #endif
112 /* Samples per channel per iteration */
113 #if defined(CPU_PP) && NUM_CORES == 1
114 #define WAV_CHUNK_SIZE 2048
115 #else
116 #define WAV_CHUNK_SIZE 1024
117 #endif
119 /**************** Little-endian handling ****************/
121 static inline unsigned get_le16( void const* p )
123 return ((unsigned char const*) p) [1] * 0x100u +
124 ((unsigned char const*) p) [0];
127 static inline int get_le16s( void const* p )
129 return ((signed char const*) p) [1] * 0x100 +
130 ((unsigned char const*) p) [0];
133 static inline void set_le16( void* p, unsigned n )
135 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
136 ((unsigned char*) p) [0] = (unsigned char) n;
139 #define GET_LE16( addr ) get_le16( addr )
140 #define GET_LE16A( addr ) get_le16( addr )
141 #define SET_LE16( addr, data ) set_le16( addr, data )
142 #define INT16A( addr ) (*(uint16_t*) (addr))
143 #define INT16SA( addr ) (*(int16_t*) (addr))
145 #ifdef ROCKBOX_LITTLE_ENDIAN
146 #define GET_LE16SA( addr ) (*( int16_t*) (addr))
147 #define SET_LE16A( addr, data ) (void) (*(uint16_t*) (addr) = (data))
148 #else
149 #define GET_LE16SA( addr ) get_le16s( addr )
150 #define SET_LE16A( addr, data ) set_le16 ( addr, data )
151 #endif
153 struct Spc_Emu;
154 #define THIS struct Spc_Emu* const this
156 /* The CPU portion (shock!) */
158 struct cpu_regs_t
160 long pc; /* more than 16 bits to allow overflow detection */
161 uint8_t a;
162 uint8_t x;
163 uint8_t y;
164 uint8_t status;
165 uint8_t sp;
168 struct src_dir
170 uint16_t start;
171 uint16_t loop;
174 struct cpu_ram_t
176 union {
177 uint8_t padding1 [0x100];
178 uint16_t align;
179 } padding1 [1];
180 union {
181 uint8_t ram [0x10000];
182 struct src_dir sd [0x10000/sizeof(struct src_dir)];
184 uint8_t padding2 [0x100];
187 #undef RAM
188 #define RAM ram.ram
189 extern struct cpu_ram_t ram;
191 long CPU_run( THIS, long start_time ) ICODE_ATTR;
192 void CPU_Init( THIS );
194 /* The DSP portion (awe!) */
195 enum { VOICE_COUNT = 8 };
196 enum { REGISTER_COUNT = 128 };
198 struct raw_voice_t
200 int8_t volume [2];
201 uint8_t rate [2];
202 uint8_t waveform;
203 uint8_t adsr [2]; /* envelope rates for attack, decay, and sustain */
204 uint8_t gain; /* envelope gain (if not using ADSR) */
205 int8_t envx; /* current envelope level */
206 int8_t outx; /* current sample */
207 int8_t unused [6];
210 struct globals_t
212 int8_t unused1 [12];
213 int8_t volume_0; /* 0C Main Volume Left (-.7) */
214 int8_t echo_feedback; /* 0D Echo Feedback (-.7) */
215 int8_t unused2 [14];
216 int8_t volume_1; /* 1C Main Volume Right (-.7) */
217 int8_t unused3 [15];
218 int8_t echo_volume_0; /* 2C Echo Volume Left (-.7) */
219 uint8_t pitch_mods; /* 2D Pitch Modulation on/off for each voice */
220 int8_t unused4 [14];
221 int8_t echo_volume_1; /* 3C Echo Volume Right (-.7) */
222 uint8_t noise_enables; /* 3D Noise output on/off for each voice */
223 int8_t unused5 [14];
224 uint8_t key_ons; /* 4C Key On for each voice */
225 uint8_t echo_ons; /* 4D Echo on/off for each voice */
226 int8_t unused6 [14];
227 uint8_t key_offs; /* 5C key off for each voice
228 (instantiates release mode) */
229 uint8_t wave_page; /* 5D source directory (wave table offsets) */
230 int8_t unused7 [14];
231 uint8_t flags; /* 6C flags and noise freq */
232 uint8_t echo_page; /* 6D */
233 int8_t unused8 [14];
234 uint8_t wave_ended; /* 7C */
235 uint8_t echo_delay; /* 7D ms >> 4 */
236 char unused9 [2];
239 enum state_t
240 { /* -1, 0, +1 allows more efficient if statements */
241 state_decay = -1,
242 state_sustain = 0,
243 state_attack = +1,
244 state_release = 2
247 struct cache_entry_t
249 int16_t const* samples;
250 unsigned end; /* past-the-end position */
251 unsigned loop; /* number of samples in loop */
252 unsigned start_addr;
255 enum { BRR_BLOCK_SIZE = 16 };
256 enum { BRR_CACHE_SIZE = 0x20000 + 32} ;
258 struct voice_t
260 #if SPC_BRRCACHE
261 int16_t const* samples;
262 long wave_end;
263 int wave_loop;
264 #else
265 int16_t samples [3 + BRR_BLOCK_SIZE + 1];
266 int block_header; /* header byte from current block */
267 #endif
268 uint8_t const* addr;
269 short volume [2];
270 long position;/* position in samples buffer, with 12-bit fraction */
271 short envx;
272 short env_mode;
273 short env_timer;
274 short key_on_delay;
277 #if SPC_BRRCACHE
278 /* a little extra for samples that go past end */
279 extern int16_t BRRcache [BRR_CACHE_SIZE];
280 #endif
282 enum { FIR_BUF_HALF = 8 };
284 #if defined(CPU_COLDFIRE)
285 /* global because of the large aligment requirement for hardware masking -
286 * L-R interleaved 16-bit samples for easy loading and mac.w use.
288 enum
290 FIR_BUF_CNT = FIR_BUF_HALF,
291 FIR_BUF_SIZE = FIR_BUF_CNT * sizeof ( int32_t ),
292 FIR_BUF_ALIGN = FIR_BUF_SIZE * 2,
293 FIR_BUF_MASK = ~((FIR_BUF_ALIGN / 2) | (sizeof ( int32_t ) - 1))
295 #elif defined (CPU_ARM)
296 enum
298 FIR_BUF_CNT = FIR_BUF_HALF * 2 * 2,
299 FIR_BUF_SIZE = FIR_BUF_CNT * sizeof ( int32_t ),
300 FIR_BUF_ALIGN = FIR_BUF_SIZE,
301 FIR_BUF_MASK = ~((FIR_BUF_ALIGN / 2) | (sizeof ( int32_t ) * 2 - 1))
303 #endif /* CPU_* */
305 struct Spc_Dsp
307 union
309 struct raw_voice_t voice [VOICE_COUNT];
310 uint8_t reg [REGISTER_COUNT];
311 struct globals_t g;
312 int16_t align;
313 } r;
315 unsigned echo_pos;
316 int keys_down;
317 int noise_count;
318 uint16_t noise; /* also read as int16_t */
320 #if defined(CPU_COLDFIRE)
321 /* circularly hardware masked address */
322 int32_t *fir_ptr;
323 /* wrapped address just behind current position -
324 allows mac.w to increment and mask fir_ptr */
325 int32_t *last_fir_ptr;
326 /* copy of echo FIR constants as int16_t for use with mac.w */
327 int16_t fir_coeff [VOICE_COUNT];
328 #elif defined (CPU_ARM)
329 /* fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code */
330 int32_t *fir_ptr;
331 /* copy of echo FIR constants as int32_t, for faster access */
332 int32_t fir_coeff [VOICE_COUNT];
333 #else
334 /* fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code */
335 int fir_pos; /* (0 to 7) */
336 int fir_buf [FIR_BUF_HALF * 2] [2];
337 /* copy of echo FIR constants as int, for faster access */
338 int fir_coeff [VOICE_COUNT];
339 #endif
341 struct voice_t voice_state [VOICE_COUNT];
343 #if SPC_BRRCACHE
344 uint8_t oldsize;
345 struct cache_entry_t wave_entry [256];
346 struct cache_entry_t wave_entry_old [256];
347 #endif
350 void DSP_run_( struct Spc_Dsp* this, long count, int32_t* out_buf ) ICODE_ATTR;
351 void DSP_reset( struct Spc_Dsp* this );
353 static inline void DSP_run( struct Spc_Dsp* this, long count, int32_t* out )
355 /* Should we just fill the buffer with silence? Flags won't be cleared */
356 /* during this run so it seems it should keep resetting every sample. */
357 if ( this->r.g.flags & 0x80 )
358 DSP_reset( this );
360 DSP_run_( this, count, out );
363 /**************** SPC emulator ****************/
364 /* 1.024 MHz clock / 32000 samples per second */
365 enum { CLOCKS_PER_SAMPLE = 32 };
367 enum { EXTRA_CLOCKS = CLOCKS_PER_SAMPLE / 2 };
369 /* using this disables timer (since this will always be in the future) */
370 enum { TIMER_DISABLED_TIME = 127 };
372 enum { ROM_SIZE = 64 };
373 enum { ROM_ADDR = 0xFFC0 };
375 enum { TIMER_COUNT = 3 };
377 struct Timer
379 long next_tick;
380 int period;
381 int count;
382 int shift;
383 int enabled;
384 int counter;
387 void Timer_run_( struct Timer* t, long time ) ICODE_ATTR;
389 static inline void Timer_run( struct Timer* t, long time )
391 if ( time >= t->next_tick )
392 Timer_run_( t, time );
395 struct Spc_Emu
397 uint8_t cycle_table [0x100];
398 struct cpu_regs_t r;
400 int32_t* sample_buf;
401 long next_dsp;
402 int rom_enabled;
403 int extra_cycles;
405 struct Timer timer [TIMER_COUNT];
407 /* large objects at end */
408 struct Spc_Dsp dsp;
409 uint8_t extra_ram [ROM_SIZE];
410 uint8_t boot_rom [ROM_SIZE];
413 enum { SPC_FILE_SIZE = 0x10180 };
415 struct spc_file_t
417 char signature [27];
418 char unused [10];
419 uint8_t pc [2];
420 uint8_t a;
421 uint8_t x;
422 uint8_t y;
423 uint8_t status;
424 uint8_t sp;
425 char unused2 [212];
426 uint8_t ram [0x10000];
427 uint8_t dsp [128];
428 uint8_t ipl_rom [128];
431 void SPC_Init( THIS );
433 int SPC_load_spc( THIS, const void* data, long size );
435 /**************** DSP interaction ****************/
436 void DSP_write( struct Spc_Dsp* this, int i, int data ) ICODE_ATTR;
438 static inline int DSP_read( struct Spc_Dsp* this, int i )
440 assert( (unsigned) i < REGISTER_COUNT );
441 return this->r.reg [i];
444 void SPC_run_dsp_( THIS, long time ) ICODE_ATTR;
446 static inline void SPC_run_dsp( THIS, long time )
448 if ( time >= this->next_dsp )
449 SPC_run_dsp_( this, time );
452 int SPC_read( THIS, unsigned addr, long const time ) ICODE_ATTR;
453 void SPC_write( THIS, unsigned addr, int data, long const time ) ICODE_ATTR;
455 /**************** Sample generation ****************/
456 int SPC_play( THIS, long count, int32_t* out ) ICODE_ATTR;
458 #endif /* _SPC_CODEC_H_ */