1) Always enable the DSP. 2) Change codec to output one 32-bit array per channel containing samples left-shifted to 28-bits (instead of 16-bit interleaved samples). 3) Remove the two 16KB internal predicterror_buffer arrays (we use the output arrays instead) 4) Small internal rearrangement of the code.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7667 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dave Chapman 2005-10-28 00:11:28 +00:00
parent 7da9477bc3
commit f1844c4166
3 changed files with 420 additions and 411 deletions

View file

@ -31,6 +31,7 @@ extern char iramend[];
#define destBufferSize (1024*16) #define destBufferSize (1024*16)
char inputBuffer[1024*32]; /* Input buffer */ char inputBuffer[1024*32]; /* Input buffer */
int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR;
size_t mdat_offset; size_t mdat_offset;
struct codec_api* rb; struct codec_api* rb;
struct codec_api* ci; struct codec_api* ci;
@ -241,11 +242,10 @@ enum codec_status codec_start(struct codec_api* api)
uint32_t elapsedtime; uint32_t elapsedtime;
uint32_t sample_duration; uint32_t sample_duration;
uint32_t sample_byte_size; uint32_t sample_byte_size;
int outputBytes; int samplesdecoded;
unsigned int i; unsigned int i;
unsigned char* buffer; unsigned char* buffer;
alac_file alac; alac_file alac;
int16_t* pDestBuffer;
/* Generic codec initialisation */ /* Generic codec initialisation */
TEST_CODEC_API(api); TEST_CODEC_API(api);
@ -261,9 +261,10 @@ enum codec_status codec_start(struct codec_api* api)
ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128)); ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128));
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_DITHER, (bool *)false); ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED); ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(28));
next_track: next_track:
@ -275,12 +276,7 @@ enum codec_status codec_start(struct codec_api* api)
while (!rb->taginfo_ready) while (!rb->taginfo_ready)
rb->yield(); rb->yield();
if (rb->id3->frequency != NATIVE_FREQUENCY) { ci->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency));
rb->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency));
rb->configure(CODEC_DSP_ENABLE, (bool *)true);
} else {
rb->configure(CODEC_DSP_ENABLE, (bool *)false);
}
stream_create(&input_stream); stream_create(&input_stream);
@ -349,9 +345,8 @@ enum codec_status codec_start(struct codec_api* api)
} }
/* Decode one block - returned samples will be host-endian */ /* Decode one block - returned samples will be host-endian */
outputBytes = destBufferSize;
rb->yield(); rb->yield();
pDestBuffer=decode_frame(&alac, buffer, &outputBytes, rb->yield); samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, rb->yield);
/* Advance codec buffer - unless we did a read */ /* Advance codec buffer - unless we did a read */
if ((char*)buffer!=(char*)inputBuffer) { if ((char*)buffer!=(char*)inputBuffer) {
@ -360,7 +355,9 @@ enum codec_status codec_start(struct codec_api* api)
/* Output the audio */ /* Output the audio */
rb->yield(); rb->yield();
while(!ci->pcmbuf_insert((char*)pDestBuffer,outputBytes)) while(!ci->pcmbuf_insert_split(outputbuffer[0],
outputbuffer[1],
samplesdecoded*sizeof(int32_t)))
rb->yield(); rb->yield();
/* Update the elapsed-time indicator */ /* Update the elapsed-time indicator */

View file

@ -51,10 +51,6 @@
int16_t predictor_coef_table[32] IBSS_ATTR; int16_t predictor_coef_table[32] IBSS_ATTR;
int16_t predictor_coef_table_a[32] IBSS_ATTR; int16_t predictor_coef_table_a[32] IBSS_ATTR;
int16_t predictor_coef_table_b[32] IBSS_ATTR; int16_t predictor_coef_table_b[32] IBSS_ATTR;
int32_t predicterror_buffer_a[4096];
int32_t predicterror_buffer_b[4096];
int32_t outputsamples_buffer_a[4096] IBSS_ATTR;
int32_t outputsamples_buffer_b[4096] IBSS_ATTR;
void alac_set_info(alac_file *alac, char *inputbuffer) void alac_set_info(alac_file *alac, char *inputbuffer)
{ {
@ -609,9 +605,9 @@ static void predictor_decompress_fir_adapt(int32_t *error_buffer,
} }
} }
void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b, void deinterlace_16(int32_t* buffer0,
int16_t *buffer_out, int32_t* buffer1,
int numchannels, int numsamples, int numsamples,
uint8_t interlacing_shift, uint8_t interlacing_shift,
uint8_t interlacing_leftweight) uint8_t interlacing_leftweight)
{ {
@ -625,11 +621,13 @@ void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b,
{ {
int32_t difference, midright; int32_t difference, midright;
midright = buffer_a[i]; midright = buffer0[i];
difference = buffer_b[i]; difference = buffer1[i];
buffer_out[i*numchannels] = (midright - ((difference * interlacing_leftweight) >> interlacing_shift)) + difference; buffer0[i] = ((midright - ((difference * interlacing_leftweight)
buffer_out[i*numchannels + 1] = midright - ((difference * interlacing_leftweight) >> interlacing_shift); >> interlacing_shift)) + difference) << SCALE16;
buffer1[i] = (midright - ((difference * interlacing_leftweight)
>> interlacing_shift)) << SCALE16;
} }
return; return;
@ -638,39 +636,21 @@ void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b,
/* otherwise basic interlacing took place */ /* otherwise basic interlacing took place */
for (i = 0; i < numsamples; i++) for (i = 0; i < numsamples; i++)
{ {
buffer_out[i*numchannels] = buffer_a[i]; buffer0[i] = buffer0[i] << SCALE16;
buffer_out[i*numchannels + 1] = buffer_b[i]; buffer1[i] = buffer1[i] << SCALE16;
} }
} }
int16_t* decode_frame(alac_file *alac,
unsigned char *inbuffer, static inline int decode_frame_mono(
int *outputsize, alac_file *alac,
int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE],
void (*yield)(void)) void (*yield)(void))
{ {
int channels;
int16_t* outbuffer;
int32_t outputsamples = alac->setinfo_max_samples_per_frame;
/* setup the stream */
alac->input_buffer = inbuffer;
alac->input_buffer_bitaccumulator = 0;
/* We can share the same buffer for outputbuffer
and outputsamples_buffer_b - and hence have them both in IRAM*/
outbuffer=(int16_t*)outputsamples_buffer_b;
channels = readbits(alac, 3);
*outputsize = outputsamples * alac->bytespersample;
switch(channels)
{
case 0: /* 1 channel */
{
int hassize; int hassize;
int isnotcompressed; int isnotcompressed;
int readsamplesize; int readsamplesize;
int outputsamples = alac->setinfo_max_samples_per_frame;
int wasted_bytes; int wasted_bytes;
int ricemodifier; int ricemodifier;
@ -694,7 +674,6 @@ int16_t* decode_frame(alac_file *alac,
/* now read the number of samples, /* now read the number of samples,
* as a 32bit integer */ * as a 32bit integer */
outputsamples = readbits(alac, 32); outputsamples = readbits(alac, 32);
*outputsize = outputsamples * alac->bytespersample;
} }
readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8); readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8);
@ -734,7 +713,7 @@ int16_t* decode_frame(alac_file *alac,
yield(); yield();
basterdised_rice_decompress(alac, basterdised_rice_decompress(alac,
predicterror_buffer_a, outputbuffer[0],
outputsamples, outputsamples,
readsamplesize, readsamplesize,
alac->setinfo_rice_initialhistory, alac->setinfo_rice_initialhistory,
@ -746,8 +725,8 @@ int16_t* decode_frame(alac_file *alac,
if (prediction_type == 0) if (prediction_type == 0)
{ /* adaptive fir */ { /* adaptive fir */
predictor_decompress_fir_adapt(predicterror_buffer_a, predictor_decompress_fir_adapt(outputbuffer[0],
outputsamples_buffer_a, outputbuffer[0],
outputsamples, outputsamples,
readsamplesize, readsamplesize,
predictor_coef_table, predictor_coef_table,
@ -777,7 +756,7 @@ int16_t* decode_frame(alac_file *alac,
audiobits = SIGN_EXTENDED32(audiobits, readsamplesize); audiobits = SIGN_EXTENDED32(audiobits, readsamplesize);
outputsamples_buffer_a[i] = audiobits; outputbuffer[0][i] = audiobits;
} }
} }
else else
@ -795,7 +774,7 @@ int16_t* decode_frame(alac_file *alac,
audiobits |= readbits(alac, readsamplesize - 16); audiobits |= readbits(alac, readsamplesize - 16);
outputsamples_buffer_a[i] = audiobits; outputbuffer[0][i] = audiobits;
} }
} }
/* wasted_bytes = 0; // unused */ /* wasted_bytes = 0; // unused */
@ -811,8 +790,8 @@ int16_t* decode_frame(alac_file *alac,
for (i = 0; i < outputsamples; i++) for (i = 0; i < outputsamples; i++)
{ {
/* Output mono data as stereo */ /* Output mono data as stereo */
outbuffer[i*2] = outputsamples_buffer_a[i]; outputbuffer[0][i] = outputbuffer[0][i] << SCALE16;
outbuffer[i*2+1] = outputsamples_buffer_a[i]; outputbuffer[1][i] = outputbuffer[0][i];
} }
break; break;
} }
@ -824,14 +803,19 @@ int16_t* decode_frame(alac_file *alac,
default: default:
break; break;
} }
break;
} return outputsamples;
case 1: /* 2 channels */ }
{
static inline int decode_frame_stereo(
alac_file *alac,
int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE],
void (*yield)(void))
{
int hassize; int hassize;
int isnotcompressed; int isnotcompressed;
int readsamplesize; int readsamplesize;
int outputsamples = alac->setinfo_max_samples_per_frame;
int wasted_bytes; int wasted_bytes;
uint8_t interlacing_shift; uint8_t interlacing_shift;
@ -855,7 +839,6 @@ int16_t* decode_frame(alac_file *alac,
/* now read the number of samples, /* now read the number of samples,
* as a 32bit integer */ * as a 32bit integer */
outputsamples = readbits(alac, 32); outputsamples = readbits(alac, 32);
*outputsize = outputsamples * alac->bytespersample;
} }
readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8) + 1; readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8) + 1;
@ -913,7 +896,7 @@ int16_t* decode_frame(alac_file *alac,
yield(); yield();
/* channel 1 */ /* channel 1 */
basterdised_rice_decompress(alac, basterdised_rice_decompress(alac,
predicterror_buffer_a, outputbuffer[0],
outputsamples, outputsamples,
readsamplesize, readsamplesize,
alac->setinfo_rice_initialhistory, alac->setinfo_rice_initialhistory,
@ -924,8 +907,8 @@ int16_t* decode_frame(alac_file *alac,
yield(); yield();
if (prediction_type_a == 0) if (prediction_type_a == 0)
{ /* adaptive fir */ { /* adaptive fir */
predictor_decompress_fir_adapt(predicterror_buffer_a, predictor_decompress_fir_adapt(outputbuffer[0],
outputsamples_buffer_a, outputbuffer[0],
outputsamples, outputsamples,
readsamplesize, readsamplesize,
predictor_coef_table_a, predictor_coef_table_a,
@ -941,7 +924,7 @@ int16_t* decode_frame(alac_file *alac,
/* channel 2 */ /* channel 2 */
basterdised_rice_decompress(alac, basterdised_rice_decompress(alac,
predicterror_buffer_b, outputbuffer[1],
outputsamples, outputsamples,
readsamplesize, readsamplesize,
alac->setinfo_rice_initialhistory, alac->setinfo_rice_initialhistory,
@ -952,8 +935,8 @@ int16_t* decode_frame(alac_file *alac,
yield(); yield();
if (prediction_type_b == 0) if (prediction_type_b == 0)
{ /* adaptive fir */ { /* adaptive fir */
predictor_decompress_fir_adapt(predicterror_buffer_b, predictor_decompress_fir_adapt(outputbuffer[1],
outputsamples_buffer_b, outputbuffer[1],
outputsamples, outputsamples,
readsamplesize, readsamplesize,
predictor_coef_table_b, predictor_coef_table_b,
@ -980,8 +963,8 @@ int16_t* decode_frame(alac_file *alac,
audiobits_a = SIGN_EXTENDED32(audiobits_a, alac->setinfo_sample_size); audiobits_a = SIGN_EXTENDED32(audiobits_a, alac->setinfo_sample_size);
audiobits_b = SIGN_EXTENDED32(audiobits_b, alac->setinfo_sample_size); audiobits_b = SIGN_EXTENDED32(audiobits_b, alac->setinfo_sample_size);
outputsamples_buffer_a[i] = audiobits_a; outputbuffer[0][i] = audiobits_a;
outputsamples_buffer_b[i] = audiobits_b; outputbuffer[1][i] = audiobits_b;
} }
} }
else else
@ -1001,8 +984,8 @@ int16_t* decode_frame(alac_file *alac,
audiobits_b = audiobits_b >> (32 - alac->setinfo_sample_size); audiobits_b = audiobits_b >> (32 - alac->setinfo_sample_size);
audiobits_b |= readbits(alac, alac->setinfo_sample_size - 16); audiobits_b |= readbits(alac, alac->setinfo_sample_size - 16);
outputsamples_buffer_a[i] = audiobits_a; outputbuffer[0][i] = audiobits_a;
outputsamples_buffer_b[i] = audiobits_b; outputbuffer[1][i] = audiobits_b;
} }
} }
/* wasted_bytes = 0; */ /* wasted_bytes = 0; */
@ -1016,10 +999,8 @@ int16_t* decode_frame(alac_file *alac,
{ {
case 16: case 16:
{ {
deinterlace_16(outputsamples_buffer_a, deinterlace_16(outputbuffer[0],
outputsamples_buffer_b, outputbuffer[1],
(int16_t*)outbuffer,
alac->numchannels,
outputsamples, outputsamples,
interlacing_shift, interlacing_shift,
interlacing_leftweight); interlacing_leftweight);
@ -1033,11 +1014,36 @@ int16_t* decode_frame(alac_file *alac,
default: default:
break; break;
} }
return outputsamples;
}
int alac_decode_frame(alac_file *alac,
unsigned char *inbuffer,
int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE],
void (*yield)(void))
{
int channels;
int outputsamples;
/* setup the stream */
alac->input_buffer = inbuffer;
alac->input_buffer_bitaccumulator = 0;
channels = readbits(alac, 3);
/* TODO: The mono and stereo functions should be combined. */
switch(channels)
{
case 0: /* 1 channel */
outputsamples=decode_frame_mono(alac,outputbuffer,yield);
break; break;
case 1: /* 2 channels */
outputsamples=decode_frame_stereo(alac,outputbuffer,yield);
break;
default: /* Unsupported */
return -1;
} }
} return outputsamples;
return outbuffer;
} }
void create_alac(int samplesize, int numchannels, alac_file* alac) void create_alac(int samplesize, int numchannels, alac_file* alac)

View file

@ -1,6 +1,12 @@
#ifndef __ALAC__DECOMP_H #ifndef __ALAC__DECOMP_H
#define __ALAC__DECOMP_H #define __ALAC__DECOMP_H
/* Always output samples shifted to 28 bits */
#define ALAC_OUTPUT_DEPTH 28
#define SCALE16 (ALAC_OUTPUT_DEPTH - 16)
#define ALAC_MAX_CHANNELS 2
#define ALAC_BLOCKSIZE 4096 /* Number of samples per channel per block */
typedef struct typedef struct
{ {
unsigned char *input_buffer; unsigned char *input_buffer;
@ -26,9 +32,9 @@ typedef struct
} alac_file; } alac_file;
void create_alac(int samplesize, int numchannels, alac_file* alac); void create_alac(int samplesize, int numchannels, alac_file* alac);
int16_t* decode_frame(alac_file *alac, int alac_decode_frame(alac_file *alac,
unsigned char *inbuffer, unsigned char *inbuffer,
int *outputsize, int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE],
void (*yield)(void)); void (*yield)(void));
void alac_set_info(alac_file *alac, char *inputbuffer); void alac_set_info(alac_file *alac, char *inputbuffer);