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:
parent
6bd8e5db08
commit
4a53787992
17 changed files with 404 additions and 38 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),¤t_section);
|
||||
|
||||
/* Read host-endian signed 24-bit PCM samples */
|
||||
n=ov_read_fixed(&vf,&pcm,1024,¤t_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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue