mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
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:
parent
dbf772bae9
commit
d4e904bf35
13 changed files with 1069 additions and 512 deletions
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
1016
apps/dsp.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
380
apps/dsp_cf.S
380
apps/dsp_cf.S
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue