SWCODEC: Dsp speed optimizations. Changes for more modularity. Removal of some usless stuff. Some assembly routines for Coldfire with speed in mind over size for the outputs but the channel modes remain compact. Miscellaneous coldfire asm updates to accomodate the changes. Codec API structure version has to increase so do a full update.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12472 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2007-02-24 17:06:36 +00:00
parent dbf772bae9
commit d4e904bf35
13 changed files with 1069 additions and 512 deletions

View file

@ -90,12 +90,12 @@
#define CODEC_ENC_MAGIC 0x52454E43 /* RENC */
/* increase this every time the api struct changes */
#define CODEC_API_VERSION 13
#define CODEC_API_VERSION 14
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */
#define CODEC_MIN_API_VERSION 13
#define CODEC_MIN_API_VERSION 14
/* codec return codes */
enum codec_status {

View file

@ -79,8 +79,6 @@ enum codec_status codec_main(void)
/* Create a decoder instance */
ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
ci->configure(DSP_SET_CLIP_MIN, -MAD_F_ONE);
ci->configure(DSP_SET_CLIP_MAX, MAD_F_ONE - 1);
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, 1024*16);
next_track:

View file

@ -712,7 +712,8 @@ static int LoadID666(unsigned char *buf) {
/**************** Codec ****************/
static int32_t samples[WAV_CHUNK_SIZE*2] IBSS_ATTR;
static int32_t samples[WAV_CHUNK_SIZE*2]
__attribute__ ((aligned (16))) IBSS_ATTR;
static struct Spc_Emu spc_emu IDATA_ATTR;

View file

@ -113,8 +113,6 @@ enum codec_status codec_main(void)
ogg_int64_t vf_pcmlengths[2];
ci->configure(DSP_SET_SAMPLE_DEPTH, 24);
ci->configure(DSP_SET_CLIP_MAX, (1 << 24) - 1);
ci->configure(DSP_SET_CLIP_MIN, -((1 << 24) - 1));
/* Note: These are sane defaults for these values. Perhaps
* they should be set differently based on quality setting
*/

1016
apps/dsp.c

File diff suppressed because it is too large Load diff

View file

@ -32,14 +32,14 @@ enum
STEREO_NUM_MODES,
};
enum {
enum
{
CODEC_SET_FILEBUF_WATERMARK = 1,
CODEC_SET_FILEBUF_CHUNKSIZE,
CODEC_SET_FILEBUF_PRESEEK,
DSP_SWITCH_CODEC,
DSP_SET_FREQUENCY,
DSP_SWITCH_FREQUENCY,
DSP_SET_CLIP_MIN,
DSP_SET_CLIP_MAX,
DSP_SET_SAMPLE_DEPTH,
DSP_SET_STEREO_MODE,
DSP_RESET,
@ -200,7 +200,7 @@ int dsp_input_count(int count);
int dsp_output_count(int count);
int dsp_stereo_mode(void);
bool dsp_configure(int setting, intptr_t value);
void dsp_set_replaygain(bool always);
void dsp_set_replaygain(void);
void dsp_set_crossfeed(bool enable);
void dsp_set_crossfeed_direct_gain(int gain);
void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff);

View file

@ -24,16 +24,26 @@
#if defined(CPU_COLDFIRE) || defined(CPU_ARM)
#define DSP_HAVE_ASM_CROSSFEED
void apply_crossfeed(int32_t* src[], int count);
void apply_crossfeed(int32_t *src[], int count);
#endif
#if defined (CPU_COLDFIRE)
#define DSP_HAVE_ASM_RESAMPLING
int dsp_downsample(int channels, int count, void *resample_data,
int32_t **src, int32_t **dst);
int dsp_upsample(int channels, int count, void *resample_data,
int32_t **src, int32_t **dst);
int dsp_downsample(int count, struct dsp_data *data, int32_t *src[], int32_t *dst[]);
int dsp_upsample(int count, struct dsp_data *data, int32_t *src[], int32_t *dst[]);
#define DSP_HAVE_ASM_SOUND_CHAN_MONO
void channels_process_sound_chan_mono(int count, int32_t *buf[]);
#define DSP_HAVE_ASM_SOUND_CHAN_CUSTOM
void channels_process_sound_chan_custom(int count, int32_t *buf[]);
#define DSP_HAVE_ASM_SOUND_CHAN_KARAOKE
void channels_process_sound_chan_karaoke(int count, int32_t *buf[]);
#define DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
void sample_output_mono(int count, struct dsp_data *data,
int32_t *src[], int16_t *dst);
#define DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO
void sample_output_stereo(int count, struct dsp_data *data,
int32_t *src[], int16_t *dst);
#endif
#endif /* _DSP_ASM_H */

View file

@ -18,7 +18,7 @@
****************************************************************************/
/****************************************************************************
* apply_crossfeed(int32_t* src[], int count)
* void apply_crossfeed(int32_t *src[], int count)
*/
.section .text
.global apply_crossfeed
@ -88,32 +88,31 @@ apply_crossfeed:
.size apply_crossfeed,.cfend-apply_crossfeed
/****************************************************************************
* dsp_downsample(int channels, int count, struct resample_data *r,
* in32_t **src, int32_t **dst)
* int dsp_downsample(int count, struct dsp_data *data,
* in32_t *src[], int32_t *dst[])
*/
.section .text
.global dsp_downsample
dsp_downsample:
lea.l -40(%sp), %sp | save non-clobberables
movem.l %d2-%d7/%a2-%a5, (%sp) |
movem.l 44(%sp), %d2-%d3/%a0-%a2| %d2 = ch = channels
| %d3 = count
| %a0 = r
movem.l 44(%sp), %d2/%a0-%a2 | %d2 = count
| %a0 = data
| %a1 = src
| %a2 = dst
move.l 4(%a0), %d4 | %d4 = delta = r->delta
move.l #16, %d7 | %d7 = shift
movem.l 4(%a0), %d3-%d4 | %d3 = ch = data->num_channels
| %d4 = delta = data->resample_data.delta
moveq.l #16, %d7 | %d7 = shift
.dschannel_loop:
move.l (%a0), %d5 | %d5 = phase = r->phase
move.l -4(%a1, %d2.l*4), %a3 | %a3 = s = src[ch-1]
move.l -4(%a2, %d2.l*4), %a4 | %a4 = d = dst[ch-1]
lea.l 4(%a0, %d2.l*4), %a5 | %a5 = &r->last_sample[ch-1]
move.l (%a5), %d0 | %d0 = last = r->last_sample[ch-1]
move.l -4(%a3, %d3.l*4), %d1 | r->last_sample[ch-1] = s[count-1]
move.l %d1, (%a5) |
move.l 12(%a0), %d5 | %d5 = phase = data->resample_data.phase
move.l -4(%a1, %d3.l*4), %a3 | %a3 = s = src[ch-1]
move.l -4(%a2, %d3.l*4), %a4 | %a4 = d = dst[ch-1]
lea.l 12(%a0, %d3.l*4), %a5 | %a5 = &data->resample_data.ast_sample[ch-1]
move.l (%a5), %d0 | %d0 = last = data->resample_data.last_sample[ch-1]
move.l -4(%a3, %d2.l*4), (%a5) | data->resample_data.last_sample[ch-1] = s[count-1]
move.l %d5, %d6 | %d6 = pos = phase >> 16
lsr.l %d7, %d6 |
cmp.l %d3, %d6 | past end of samples?
cmp.l %d2, %d6 | past end of samples?
bge.b .dsloop_skip | yes? skip loop
tst.l %d6 | need last sample of prev. frame?
bne.b .dsloop | no? start main loop
@ -134,14 +133,14 @@ dsp_downsample:
move.l %d5, %d6 | pos = phase >> 16
lsr.l %d7, %d6 |
move.l %d0, (%a4)+ | *d++ = %d0
cmp.l %d3, %d6 | pos < count?
cmp.l %d2, %d6 | pos < count?
blt.b .dsloop | yes? continue resampling
.dsloop_skip:
subq.l #1, %d2 | ch > 0?
subq.l #1, %d3 | ch > 0?
bgt.b .dschannel_loop | yes? process next channel
asl.l %d7, %d3 | wrap phase to start of next frame
sub.l %d3, %d5 | r->phase = phase - (count << 16)
move.l %d5, (%a0) |
asl.l %d7, %d2 | wrap phase to start of next frame
sub.l %d2, %d5 | data->resample_data.phase =
move.l %d5, 12(%a0) | ... phase - (count << 16)
move.l %a4, %d0 | return d - d[0]
sub.l (%a2), %d0 |
asr.l #2, %d0 | convert bytes->samples
@ -153,31 +152,30 @@ dsp_downsample:
.size dsp_downsample,.dsend-dsp_downsample
/****************************************************************************
* dsp_upsample(int channels, int count, struct resample_data *r,
* in32_t **src, int32_t **dst)
* int dsp_upsample(int count, struct dsp_data *dsp,
* in32_t *src[], int32_t *dst[])
*/
.section .text
.global dsp_upsample
dsp_upsample:
lea.l -40(%sp), %sp | save non-clobberables
movem.l %d2-%d7/%a2-%a5, (%sp) |
movem.l 44(%sp), %d2-%d3/%a0-%a2| %d2 = ch = channels
| %d3 = count
| %a0 = r
movem.l 44(%sp), %d2/%a0-%a2 | %d2 = count
| %a0 = data
| %a1 = src
| %a2 = dst
move.l 4(%a0), %d4 | %d4 = delta = r->delta
movem.l 4(%a0), %d3-%d4 | %d3 = ch = channels
| %d4 = delta = data->resample_data.delta
swap %d4 | swap delta to high word to use
| carries to increment position
.uschannel_loop:
move.l (%a0), %d5 | %d5 = phase = r->phase
move.l -4(%a1, %d2.l*4), %a3 | %a3 = s = src[ch-1]
lea.l 4(%a0, %d2.l*4), %a4 | %a4 = &r->last_sample[ch-1]
lea.l (%a3, %d3.l*4), %a5 | %a5 = src_end = &src[count]
move.l (%a4), %d0 | %d0 = last = r->last_sample[ch-1]
move.l -4(%a5), %d1 | r->last_sample[ch-1] = s[count-1]
move.l %d1, (%a4) |
move.l -4(%a2, %d2.l*4), %a4 | %a4 = d = dst[ch-1]
move.l 12(%a0), %d5 | %d5 = phase = data->resample_data.phase
move.l -4(%a1, %d3.l*4), %a3 | %a3 = s = src[ch-1]
lea.l 12(%a0, %d3.l*4), %a4 | %a4 = &data->resample_data.last_sample[ch-1]
lea.l (%a3, %d2.l*4), %a5 | %a5 = src_end = &src[count]
move.l (%a4), %d0 | %d0 = last = data->resample_data.last_sample[ch-1]
move.l -(%a5), (%a4) | data->resample_data.last_sample[ch-1] = s[count-1]
move.l -4(%a2, %d3.l*4), %a4 | %a4 = d = dst[ch-1]
swap %d5 | swap phase to high word to use
| carries to increment position
move.l %d5, %d6 | %d6 = pos = phase >> 16
@ -204,13 +202,13 @@ dsp_upsample:
move.l %d7, (%a4)+ | *d++ = %d7
add.l %d4, %d5 | phase += delta
bcc.b .usloop_0 | load next values?
cmp.l %a5, %a3 | src < src_end?
blt.b .usloop_1 | yes? continue resampling
cmp.l %a5, %a3 | src <= src_end?
ble.b .usloop_1 | yes? continue resampling
.usloop_skip:
subq.l #1, %d2 | ch > 0?
subq.l #1, %d3 | ch > 0?
bgt.b .uschannel_loop | yes? process next channel
swap %d5 | wrap phase to start of next frame
move.l %d5, (%a0) | ...and save in r->phase
move.l %d5, 12(%a0) | ...and save in data->resample_data.phase
move.l %a4, %d0 | return d - d[0]
sub.l (%a2), %d0 |
movem.l (%sp), %d2-%d7/%a2-%a5 | restore non-clobberables
@ -219,3 +217,307 @@ dsp_upsample:
rts | buh-bye
.usend:
.size dsp_upsample,.usend-dsp_upsample
/* These routines might benefit from burst transfers but we'll keep them
* small for now since they're rather light weight
*/
/****************************************************************************
* void channels_process_sound_chan_mono(int count, int32_t *buf[])
*
* Mix left and right channels 50/50 into a center channel.
*/
.section .text
.global channels_process_sound_chan_mono
channels_process_sound_chan_mono:
movem.l 4(%sp), %d0/%a0 | %d0 = count, %a0 = buf
lea.l -12(%sp), %sp | save registers
move.l %macsr, %d1 |
movem.l %d1-%d3, (%sp) |
move.l #0xb0, %macsr | put emac in rounding fractional mode
movem.l (%a0), %a0-%a1 | get channel pointers
move.l #0x40000000, %d3 | %d3 = 0.5
1:
move.l (%a0), %d1 | L = R = l/2 + r/2
mac.l %d1, %d3, (%a1), %d2, %acc0 |
mac.l %d2, %d3, %acc0 |
movclr.l %acc0, %d1 |
move.l %d1, (%a0)+ | output to original buffer
move.l %d1, (%a1)+ |
subq.l #1, %d0 |
bgt.s 1b |
movem.l (%sp), %d1-%d3 | restore registers
move.l %d1, %macsr |
lea.l 12(%sp), %sp | cleanup
rts
.cpmono_end:
.size channels_process_sound_chan_mono, .cpmono_end-channels_process_sound_chan_mono
/****************************************************************************
* void channels_process_sound_chan_custom(int count, int32_t *buf[])
*
* Apply stereo width (narrowing/expanding) effect.
*/
.section .text
.global channels_process_sound_chan_custom
channels_process_sound_chan_custom:
movem.l 4(%sp), %d0/%a0 | %d0 = count, %a0 = buf
lea.l -16(%sp), %sp | save registers
move.l %macsr, %d1 |
movem.l %d1-%d4, (%sp) |
move.l #0xb0, %macsr | put emac in rounding fractional mode
movem.l (%a0), %a0-%a1 | get channel pointers
move.l dsp_sw_gain, %d3 | load straight (mid) gain
move.l dsp_sw_cross, %d4 | load cross (side) gain
1:
move.l (%a0), %d1 |
mac.l %d1, %d3 , (%a1), %d2, %acc0 | L = l*gain + r*cross
mac.l %d1, %d4 , %acc1 | R = r*gain + l*cross
mac.l %d2, %d4 , %acc0 |
mac.l %d2, %d3 , %acc1 |
movclr.l %acc0, %d1 |
movclr.l %acc1, %d2 |
move.l %d1, (%a0)+ |
move.l %d2, (%a1)+ |
subq.l #1, %d0 |
bgt.s 1b |
movem.l (%sp), %d1-%d4 | restore registers
move.l %d1, %macsr |
lea.l 16(%sp), %sp | cleanup
rts
.cpcustom_end:
.size channels_process_sound_chan_custom, .cpcustom_end-channels_process_sound_chan_custom
/****************************************************************************
* void channels_process_sound_chan_karaoke(int count, int32_t *buf[])
*
* Separate channels into side channels.
*/
.section .text
.global channels_process_sound_chan_karaoke
channels_process_sound_chan_karaoke:
movem.l 4(%sp), %d0/%a0 | %d0 = count, %a0 = buf
lea.l -16(%sp), %sp | save registers
move.l %macsr, %d1 |
movem.l %d1-%d4, (%sp) |
move.l #0xb0, %macsr | put emac in rounding fractional mode
movem.l (%a0), %a0-%a1 | get channel pointers
move.l #0x40000000, %d4 | %d3 = 0.5
1:
move.l (%a0), %d1 |
mac.l %d1, %d4, (%a1), %d2, %acc0 | L = l/2 - r/2
mac.l %d2, %d4, %acc1 | R = r/2 - l/2
movclr.l %acc0, %d1 |
movclr.l %acc1, %d2 |
move.l %d1, %d3 |
sub.l %d2, %d1 |
sub.l %d3, %d2 |
move.l %d1, (%a0)+ |
move.l %d2, (%a1)+ |
subq.l #1, %d0 |
bgt.s 1b |
movem.l (%sp), %d1-%d4 | restore registers
move.l %d1, %macsr |
lea.l 16(%sp), %sp | cleanup
rts
.cpkaraoke_end:
.size channels_process_sound_chan_karaoke, .cpkaraoke_end-channels_process_sound_chan_karaoke
/****************************************************************************
* void sample_output_stereo(int count, struct dsp_data *data,
* int32_t *src[], int16_t *dst)
*
* Framework based on the ubiquitous Rockbox line transfer logic for
* Coldfire CPUs.
*
* Does emac clamping and scaling (which proved faster than the usual
* checks and branches - even single test clamping) and writes using
* line burst transfers. Also better than writing a single L-R pair per
* loop but a good deal more code.
*
* Attemping bursting during reads is rather futile since the source and
* destination alignments rarely agree and too much complication will
* slow us up. The parallel loads seem to do a bit better at least until
* a pcm buffer can always give line aligned chunk and then aligning the
* dest can then imply the source is aligned if the source buffers are.
* For now longword alignment is assumed of both the source and dest.
*
*/
.section .text
.global sample_output_stereo
sample_output_stereo:
lea.l -44(%sp), %sp | save registers
move.l %macsr, %d1 | do it now as at many lines will
movem.l %d1-%d7/%a2-%a5, (%sp) | be the far more common condition
move.l #0x80, %macsr | put emac unit in signed int mode
movem.l 48(%sp), %a0-%a2/%a4 |
lea.l (%a4, %a0.l*4), %a0 | %a0 = end address
move.l (%a1), %d1 | %a1 = multiplier: (1 << (16 - scale))
sub.l #16, %d1 |
neg.l %d1 |
move.q #1, %d0 |
asl.l %d1, %d0 |
move.l %d0, %a1 |
movem.l (%a2), %a2-%a3 | get L/R channel pointers
moveq.l #28, %d0 | %d0 = second line bound
add.l %a4, %d0 |
and.l #0xfffffff0, %d0 |
cmp.l %a4, %d0 | at least a full line?
blo.w .sos_longloop_1_start | no? jump to trailing longword
sub.l #16, %d0 | %d1 = first line bound
cmp.l %a4, %d0 | any leading longwords?
bls.b .sos_lineloop_start | no? jump to line loop
.sos_longloop_0:
move.l (%a2)+, %d1 | read longword from L and R
mac.l %d1, %a1, (%a3)+, %d2, %acc0 | shift L to high word
mac.l %d2, %a1, %acc1 | shift R to high word
movclr.l %acc0, %d1 | get possibly saturated results
movclr.l %acc1, %d2 |
swap %d2 | move R to low word
move.w %d2, %d1 | interleave MS 16 bits of each
move.l %d1, (%a4)+ | ...and write both
cmp.l %a4, %d0 |
bhi.b .sos_longloop_0 |
.sos_lineloop_start:
lea.l -12(%a0), %a5 | %a5 = at or just before last line bound
.sos_lineloop:
move.l (%a2)+, %d0 | get next 4 L samples and scale
mac.l %d0, %a1, (%a2)+, %d1, %acc0 | with saturation
mac.l %d1, %a1, (%a2)+, %d2, %acc1 |
mac.l %d2, %a1, (%a2)+, %d3, %acc2 |
mac.l %d3, %a1, %acc3 |
movclr.l %acc0, %d0 | obtain results
movclr.l %acc1, %d1 |
movclr.l %acc2, %d2 |
movclr.l %acc3, %d3 |
move.l (%a3)+, %d4 | get next 4 R samples and scale
mac.l %d4, %a1, (%a3)+, %d5, %acc0 | with saturation
mac.l %d5, %a1, (%a3)+, %d6, %acc1 |
mac.l %d6, %a1, (%a3)+, %d7, %acc2 |
mac.l %d7, %a1, %acc3 |
movclr.l %acc0, %d4 | obtain results
movclr.l %acc1, %d5 |
movclr.l %acc2, %d6 |
movclr.l %acc3, %d7 |
swap %d4 | interleave most significant
move.w %d4, %d0 | 16 bits of L and R
swap %d5 |
move.w %d5, %d1 |
swap %d6 |
move.w %d6, %d2 |
swap %d7 |
move.w %d7, %d3 |
movem.l %d0-%d3, (%a4) | write four stereo samples
lea.l 16(%a4), %a4 |
cmp.l %a4, %a5 |
bhi.b .sos_lineloop |
.sos_longloop_1_start:
cmp.l %a4, %a0 | any longwords left?
bls.b .sos_done | no? finished.
.sos_longloop_1:
move.l (%a2)+, %d1 | handle trailing longwords
mac.l %d1, %a1, (%a3)+, %d2, %acc0 | the same way as leading ones
mac.l %d2, %a1, %acc1 |
movclr.l %acc0, %d1 |
movclr.l %acc1, %d2 |
swap %d2 |
move.w %d2, %d1 |
move.l %d1, (%a4)+ |
cmp.l %a4, %a0 |
bhi.b .sos_longloop_1 |
.sos_done:
movem.l (%sp), %d1-%d7/%a2-%a5 | restore registers
move.l %d1, %macsr |
lea.l 44(%sp), %sp | cleanup
rts |
.sos_end:
.size sample_output_stereo, .sos_end-sample_output_stereo
/****************************************************************************
* void sample_output_mono(int count, struct dsp_data *data,
* int32_t *src[], int16_t *dst)
*
* Same treatment as sample_output_stereo but for one channel.
*/
.section .text
.global sample_output_mono
sample_output_mono:
lea.l -28(%sp), %sp | save registers
move.l %macsr, %d1 | do it now as at many lines will
movem.l %d1-%d5/%a2-%a3, (%sp) | be the far more common condition
move.l #0x80, %macsr | put emac unit in signed int mode
movem.l 32(%sp), %a0-%a3 |
lea.l (%a3, %a0.l*4), %a0 | %a0 = end address
move.l (%a1), %d1 | %d5 = multiplier: (1 << (16 - scale))
sub.l #16, %d1 |
neg.l %d1 |
move.q #1, %d5 |
asl.l %d1, %d5 |
movem.l (%a2), %a2 | get source channel pointer
moveq.l #28, %d0 | %d0 = second line bound
add.l %a3, %d0 |
and.l #0xfffffff0, %d0 |
cmp.l %a3, %d0 | at least a full line?
blo.w .som_longloop_1_start | no? jump to trailing longword
sub.l #16, %d0 | %d1 = first line bound
cmp.l %a3, %d0 | any leading longwords?
bls.b .som_lineloop_start | no? jump to line loop
.som_longloop_0:
move.l (%a2)+, %d1 | read longword from L and R
mac.l %d1, %d5, %acc0 | shift L to high word
movclr.l %acc0, %d1 | get possibly saturated results
move.l %d1, %d2 |
swap %d2 | move R to low word
move.w %d2, %d1 | duplicate single channel into
move.l %d1, (%a3)+ | L and R
cmp.l %a3, %d0 |
bhi.b .som_longloop_0 |
.som_lineloop_start:
lea.l -12(%a0), %a1 | %a1 = at or just before last line bound
.som_lineloop:
move.l (%a2)+, %d0 | get next 4 L samples and scale
mac.l %d0, %d5, (%a2)+, %d1, %acc0 | with saturation
mac.l %d1, %d5, (%a2)+, %d2, %acc1 |
mac.l %d2, %d5, (%a2)+, %d3, %acc2 |
mac.l %d3, %d5, %acc3 |
movclr.l %acc0, %d0 | obtain results
movclr.l %acc1, %d1 |
movclr.l %acc2, %d2 |
movclr.l %acc3, %d3 |
move.l %d0, %d4 | duplicate single channel
swap %d4 | into L and R
move.w %d4, %d0 |
move.l %d1, %d4 |
swap %d4 |
move.w %d4, %d1 |
move.l %d2, %d4 |
swap %d4 |
move.w %d4, %d2 |
move.l %d3, %d4 |
swap %d4 |
move.w %d4, %d3 |
movem.l %d0-%d3, (%a3) | write four stereo samples
lea.l 16(%a3), %a3 |
cmp.l %a3, %a1 |
bhi.b .som_lineloop |
.som_longloop_1_start:
cmp.l %a3, %a0 | any longwords left?
bls.b .som_done | no? finished.
.som_longloop_1:
move.l (%a2)+, %d1 | handle trailing longwords
mac.l %d1, %d5, %acc0 | the same way as leading ones
movclr.l %acc0, %d1 |
move.l %d1, %d2 |
swap %d2 |
move.w %d2, %d1 |
move.l %d1, (%a3)+ |
cmp.l %a3, %a0 |
bhi.b .som_longloop_1 |
.som_done:
movem.l (%sp), %d1-%d5/%a2-%a3 | restore registers
move.l %d1, %macsr |
lea.l 28(%sp), %sp | cleanup
rts |
.som_end:
.size sample_output_mono, .som_end-sample_output_mono

View file

@ -109,7 +109,7 @@ int replaygain_callback(int action,const struct menu_item_ex *this_item)
switch (action)
{
case ACTION_EXIT_MENUITEM: /* on exit */
dsp_set_replaygain(true);
dsp_set_replaygain();
break;
}
return action;
@ -208,7 +208,7 @@ int playback_callback(int action,const struct menu_item_ex *this_item)
&& (audio_status() & AUDIO_STATUS_PLAY))
{
#if CONFIG_CODEC == SWCODEC
dsp_set_replaygain(true);
dsp_set_replaygain();
#endif
if (global_settings.playlist_shuffle)
{

View file

@ -276,6 +276,7 @@ static size_t high_watermark; /* High watermark for rebuffer (A/V/other) */
#endif
/* Multiple threads */
static void set_current_codec(int codec_idx);
static const char *get_codec_filename(int enc_spec); /* (A-/C-/V-) */
/* Set the watermark to trigger buffer fill (A/C) FIXME */
static void set_filebuf_watermark(int seconds);
@ -299,7 +300,7 @@ IBSS_ATTR;
static const char codec_thread_name[] = "codec";
struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
/* Voice thread */
#ifdef PLAYBACK_VOICE
@ -840,7 +841,7 @@ void audio_preinit(void)
logf("playback system pre-init");
filling = false;
current_codec = CODEC_IDX_AUDIO;
set_current_codec(CODEC_IDX_AUDIO);
playing = false;
paused = false;
audio_codec_loaded = false;
@ -918,6 +919,12 @@ void voice_stop(void)
/* --- Routines called from multiple threads --- */
static void set_current_codec(int codec_idx)
{
current_codec = codec_idx;
dsp_configure(DSP_SWITCH_CODEC, codec_idx);
}
#ifdef PLAYBACK_VOICE
static void swap_codec(void)
{
@ -961,7 +968,7 @@ skip_iram_swap:
mutex_lock(&mutex_codecthread);
/* Take control */
current_codec = my_codec;
set_current_codec(my_codec);
/* Reload our IRAM and DRAM */
memcpy((unsigned char *)CODEC_IRAM_ORIGIN, iram_buf[my_codec],
@ -1284,7 +1291,7 @@ static void voice_thread(void)
logf("Loading voice codec");
voice_codec_loaded = true;
mutex_lock(&mutex_codecthread);
current_codec = CODEC_IDX_VOICE;
set_current_codec(CODEC_IDX_VOICE);
dsp_configure(DSP_RESET, 0);
voice_remaining = 0;
voice_getmore = NULL;
@ -1941,7 +1948,7 @@ static void codec_thread(void)
}
mutex_lock(&mutex_codecthread);
#endif
current_codec = CODEC_IDX_AUDIO;
set_current_codec(CODEC_IDX_AUDIO);
ci.stop_codec = false;
status = codec_load_file((const char *)ev.data, &ci);
#ifdef PLAYBACK_VOICE
@ -1972,7 +1979,7 @@ static void codec_thread(void)
}
mutex_lock(&mutex_codecthread);
#endif
current_codec = CODEC_IDX_AUDIO;
set_current_codec(CODEC_IDX_AUDIO);
ci.stop_codec = false;
wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
@ -1995,7 +2002,7 @@ static void codec_thread(void)
mutex_lock(&mutex_codecthread);
#endif
logf("loading encoder");
current_codec = CODEC_IDX_AUDIO;
set_current_codec(CODEC_IDX_AUDIO);
ci.stop_codec = false;
status = codec_load_file((const char *)ev.data, &ci);
#ifdef PLAYBACK_VOICE
@ -2702,12 +2709,12 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
{
int last_codec = current_codec;
current_codec = CODEC_IDX_AUDIO;
set_current_codec(CODEC_IDX_AUDIO);
conf_watermark = AUDIO_DEFAULT_WATERMARK;
conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
dsp_configure(DSP_RESET, 0);
current_codec = last_codec;
set_current_codec(last_codec);
}
/* Get track metadata if we don't already have it. */

View file

@ -703,7 +703,7 @@ bool quick_screen_quick(int button_enter)
&& audio_status() & AUDIO_STATUS_PLAY)
{
#if CONFIG_CODEC == SWCODEC
dsp_set_replaygain(true);
dsp_set_replaygain();
#endif
if (global_settings.playlist_shuffle)
playlist_randomise(NULL, current_tick, true);

View file

@ -822,7 +822,7 @@ void settings_apply(void)
#if CONFIG_CODEC == SWCODEC
audio_set_crossfade(global_settings.crossfade);
dsp_set_replaygain(true);
dsp_set_replaygain();
dsp_set_crossfeed(global_settings.crossfeed);
dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain);
dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain,

View file

@ -63,6 +63,7 @@ enum {
SOUND_CHAN_MONO_LEFT,
SOUND_CHAN_MONO_RIGHT,
SOUND_CHAN_KARAOKE,
SOUND_CHAN_NUM_MODES
};
typedef void sound_set_type(int value);