1
0
Fork 0
forked from len0rd/rockbox

ReplayGain support for Ogg Vorbis files (also called VorbisGain) added.

Note that there is a small delay from leaving a setting until the change
can be heard (due to audio data buffering).


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7234 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Magnus Holmgren 2005-07-24 15:32:28 +00:00
parent 6bd8e5db08
commit 4a53787992
17 changed files with 404 additions and 38 deletions

View file

@ -121,6 +121,8 @@ extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link);
extern long ov_read(OggVorbis_File *vf,char *buffer,int length,
int *bitstream);
extern long ov_read_fixed(OggVorbis_File *vf,ogg_int32_t ***pcm_channels,
int length,int *bitstream);
#ifdef __cplusplus
}

View file

@ -1604,3 +1604,47 @@ long ov_read(OggVorbis_File *vf,char *buffer,int bytes_req,int *bitstream){
return(samples);
}
}
/* input values: pcm_channels) a float vector per channel of output
length) the sample length being read by the app
return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
0) EOF
n) number of samples of PCM actually returned. The
below works on a packet-by-packet basis, so the
return length is not related to the 'length' passed
in, just guaranteed to fit.
*section) set to the logical bitstream number */
long ov_read_fixed(OggVorbis_File *vf,ogg_int32_t ***pcm_channels,int length,
int *bitstream){
if(vf->ready_state<OPENED)return(OV_EINVAL);
#if CONFIG_CPU == MCF5249
mcf5249_init_mac();
#endif
while(1){
if(vf->ready_state==INITSET){
ogg_int32_t **pcm;
long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
if(samples){
if(pcm_channels)*pcm_channels=pcm;
if(samples>length)samples=length;
vorbis_synthesis_read(&vf->vd,samples);
vf->pcm_offset+=samples;
if(bitstream)*bitstream=vf->current_link;
return samples;
}
}
/* suck in another packet */
{
int ret=_fetch_and_process_packet(vf,1,1);
if(ret==OV_EOF)return(0);
if(ret<=0)return(ret);
}
}
}

View file

@ -23,6 +23,7 @@
#include "playback.h"
#include "codeclib.h"
#include "xxx2wav.h"
#include "id3.h"
struct codec_api *local_rb;
@ -34,3 +35,11 @@ int codec_init(struct codec_api* rb)
return 0;
}
void codec_set_replaygain(struct mp3entry* id3)
{
local_rb->configure(DSP_SET_TRACK_GAIN, (long *) id3->track_gain);
local_rb->configure(DSP_SET_ALBUM_GAIN, (long *) id3->album_gain);
local_rb->configure(DSP_SET_TRACK_PEAK, (long *) id3->track_peak);
local_rb->configure(DSP_SET_ALBUM_PEAK, (long *) id3->album_peak);
}

View file

@ -37,4 +37,4 @@ int memcmp(const void *s1, const void *s2, size_t n);
void* memmove(const void *s1, const void *s2, size_t n);
int codec_init(struct codec_api* rb);
void codec_set_replaygain(struct mp3entry* id3);

View file

@ -105,16 +105,11 @@ bool vorbis_set_codec_parameters(OggVorbis_File *vf)
return false;
}
if (rb->id3->frequency != NATIVE_FREQUENCY) {
rb->configure(CODEC_DSP_ENABLE, (bool *)true);
} else {
rb->configure(CODEC_DSP_ENABLE, (bool *)false);
}
rb->configure(DSP_SET_FREQUENCY, (int *)rb->id3->frequency);
codec_set_replaygain(rb->id3);
if (vi->channels == 2) {
rb->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED);
rb->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
} else if (vi->channels == 1) {
rb->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO);
}
@ -129,14 +124,12 @@ extern char iramend[];
#endif
/* reserve the PCM buffer in the IRAM area */
static char pcmbuf[4096] IDATA_ATTR;
/* this is the codec entry point */
enum codec_status codec_start(struct codec_api* api)
{
ov_callbacks callbacks;
OggVorbis_File vf;
ogg_int32_t** pcm;
int error;
long n;
@ -157,10 +150,12 @@ enum codec_status codec_start(struct codec_api* api)
#ifdef USE_IRAM
rb->memcpy(iramstart, iramcopy, iramend-iramstart);
#endif
rb->configure(DSP_DITHER, (bool *)false);
rb->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16));
rb->configure(CODEC_DSP_ENABLE, (bool *)true);
rb->configure(DSP_DITHER, (bool *)false);
rb->configure(DSP_SET_SAMPLE_DEPTH, (long *) (24));
rb->configure(DSP_SET_CLIP_MAX, (long *) ((1 << 24) - 1));
rb->configure(DSP_SET_CLIP_MIN, (long *) -((1 << 24) - 1));
/* Note: These are sane defaults for these values. Perhaps
* they should be set differently based on quality setting
*/
@ -244,9 +239,9 @@ enum codec_status codec_start(struct codec_api* api)
}
rb->seek_time = 0;
}
/* Read host-endian signed 16 bit PCM samples */
n=ov_read(&vf,pcmbuf,sizeof(pcmbuf),&current_section);
/* Read host-endian signed 24-bit PCM samples */
n=ov_read_fixed(&vf,&pcm,1024,&current_section);
/* Change DSP and buffer settings for this bitstream */
if ( current_section != previous_section ) {
@ -262,9 +257,10 @@ enum codec_status codec_start(struct codec_api* api)
} else if (n < 0) {
DEBUGF("Error decoding frame\n");
} else {
while (!rb->pcmbuf_insert(pcmbuf, n)) {
while (!rb->pcmbuf_insert_split(pcm[0], pcm[1],
n * sizeof(ogg_int32_t))) {
rb->sleep(1);
}
}
rb->set_offset(ov_raw_tell(&vf));
rb->set_elapsed(ov_time_tell(&vf));