rewrite replaygain code, needs testing
git-svn-id: https://svn.musicpd.org/mpd/trunk@2482 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
@@ -362,7 +362,7 @@ int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
sampleBufferLen = sampleCount*2;
|
||||
|
||||
sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer,
|
||||
sampleBufferLen, time, bitRate);
|
||||
sampleBufferLen, time, bitRate, NULL);
|
||||
if(dc->seek) {
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
|
||||
@@ -116,7 +116,8 @@ int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
ret*fs,
|
||||
(float)current /
|
||||
(float)dc->audioFormat.sampleRate,
|
||||
bitRate);
|
||||
bitRate,
|
||||
NULL);
|
||||
if(dc->stop) break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ typedef struct {
|
||||
OutputBuffer * cb;
|
||||
DecoderControl * dc;
|
||||
InputStream inStream;
|
||||
float replayGainScale;
|
||||
char * path;
|
||||
ReplayGainInfo * replayGainInfo;
|
||||
} FlacData;
|
||||
|
||||
/* this code is based on flac123, from flac-tools */
|
||||
@@ -82,7 +82,7 @@ int flac_decode(OutputBuffer * cb, DecoderControl *dc, char * path) {
|
||||
data.bitRate = 0;
|
||||
data.cb = cb;
|
||||
data.dc = dc;
|
||||
data.replayGainScale = 1.0;
|
||||
data.replayGainInfo = NULL;
|
||||
data.path = path;
|
||||
|
||||
if(openInputStream(&(data.inStream), path)<0) {
|
||||
@@ -195,6 +195,8 @@ int flac_decode(OutputBuffer * cb, DecoderControl *dc, char * path) {
|
||||
else dc->state = DECODE_STATE_STOP;
|
||||
|
||||
fail:
|
||||
if(data.replayGainInfo) freeReplayGainInfo(data.replayGainInfo);
|
||||
|
||||
if(streamOpen) closeInputStream(&(data.inStream));
|
||||
|
||||
if(flacDec) FLAC__seekable_stream_decoder_delete(flacDec);
|
||||
@@ -338,30 +340,28 @@ int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block, char * cmnt,
|
||||
|
||||
/* replaygain stuff by AliasMrJones */
|
||||
void flacParseReplayGain(const FLAC__StreamMetadata *block, FlacData * data) {
|
||||
int found;
|
||||
float gain = 0.0;
|
||||
float peak = 0.0;
|
||||
int state = getReplayGainState();
|
||||
if(NULL == data->replayGainInfo) {
|
||||
freeReplayGainInfo(data->replayGainInfo);
|
||||
data->replayGainInfo = NULL;
|
||||
}
|
||||
|
||||
if(state == REPLAYGAIN_OFF) return;
|
||||
data->replayGainInfo = newReplayGainInfo();
|
||||
|
||||
found = flacFindVorbisCommentFloat(block,"replaygain_album_gain",&gain);
|
||||
if(found) {
|
||||
flacFindVorbisCommentFloat(block,"replaygain_album_peak",
|
||||
&peak);
|
||||
}
|
||||
int found = 0;
|
||||
|
||||
if(!found || state == REPLAYGAIN_TRACK) {
|
||||
found = flacFindVorbisCommentFloat(block,
|
||||
"replaygain_track_gain", &gain);
|
||||
if(found) {
|
||||
peak = 0.0;
|
||||
flacFindVorbisCommentFloat(block,
|
||||
"replaygain_track_peak",&peak);
|
||||
}
|
||||
}
|
||||
found &= flacFindVorbisCommentFloat(block,"replaygain_album_gain",
|
||||
&data->replayGainInfo->albumGain);
|
||||
found &= flacFindVorbisCommentFloat(block,"replaygain_album_peak",
|
||||
&data->replayGainInfo->albumPeak);
|
||||
found &= flacFindVorbisCommentFloat(block,"replaygain_track_gain",
|
||||
&data->replayGainInfo->trackGain);
|
||||
found &= flacFindVorbisCommentFloat(block,"replaygain_track_peak",
|
||||
&data->replayGainInfo->trackPeak);
|
||||
|
||||
if(found) data->replayGainScale = computeReplayGainScale(gain,peak);
|
||||
if(!found) {
|
||||
freeReplayGainInfo(data->replayGainInfo);
|
||||
data->replayGainInfo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void flacMetadata(const FLAC__SeekableStreamDecoder *dec,
|
||||
@@ -391,11 +391,9 @@ void flacMetadata(const FLAC__SeekableStreamDecoder *dec,
|
||||
}
|
||||
|
||||
int flacSendChunk(FlacData * data) {
|
||||
doReplayGain(data->chunk,data->chunk_length,&(data->dc->audioFormat),
|
||||
data->replayGainScale);
|
||||
|
||||
switch(sendDataToOutputBuffer(data->cb, NULL, data->dc, 1, data->chunk,
|
||||
data->chunk_length, data->time, data->bitRate))
|
||||
data->chunk_length, data->time, data->bitRate,
|
||||
data->replayGainInfo))
|
||||
{
|
||||
case OUTPUT_BUFFER_DC_STOP:
|
||||
return -1;
|
||||
|
||||
@@ -191,7 +191,7 @@ int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
time += ret*secPerByte;
|
||||
sendDataToOutputBuffer(cb, NULL, dc, 0,
|
||||
(char *)data->audio_buffer, ret, time,
|
||||
0);
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
flushOutputBuffer(cb);
|
||||
|
||||
@@ -585,7 +585,8 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
|
||||
data->outputPtr-
|
||||
data->outputBuffer,
|
||||
data->elapsedTime,
|
||||
data->bitRate/1000);
|
||||
data->bitRate/1000,
|
||||
NULL);
|
||||
if(ret == OUTPUT_BUFFER_DC_STOP) {
|
||||
data->flush = 0;
|
||||
return DECODE_BREAK;
|
||||
@@ -710,7 +711,8 @@ int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) {
|
||||
data.inStream->seekable,
|
||||
data.outputBuffer,
|
||||
data.outputPtr-data.outputBuffer,
|
||||
data.elapsedTime,data.bitRate/1000);
|
||||
data.elapsedTime,data.bitRate/1000,
|
||||
NULL);
|
||||
}
|
||||
|
||||
closeInputStream(inStream);
|
||||
|
||||
@@ -284,7 +284,7 @@ int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
sampleBuffer+=offset*channels*2;
|
||||
|
||||
sendDataToOutputBuffer(cb, NULL, dc, 1, sampleBuffer,
|
||||
sampleBufferLen, time, bitRate);
|
||||
sampleBufferLen, time, bitRate, NULL);
|
||||
if(dc->stop) {
|
||||
eof = 1;
|
||||
break;
|
||||
|
||||
@@ -114,62 +114,45 @@ char * ogg_parseComment(char * comment, char * needle) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float ogg_getReplayGainScale(char ** comments) {
|
||||
int trackGainFound = 0;
|
||||
int albumGainFound = 0;
|
||||
float trackGain = 1.0;
|
||||
float albumGain = 1.0;
|
||||
float trackPeak = 0.0;
|
||||
float albumPeak = 0.0;
|
||||
void ogg_getReplayGainInfo(char ** comments, ReplayGainInfo ** infoPtr) {
|
||||
char * temp;
|
||||
int replayGainState = getReplayGainState();
|
||||
int found = 0;
|
||||
|
||||
if(replayGainState == REPLAYGAIN_OFF) return 1.0;
|
||||
if(*infoPtr) freeReplayGainInfo(*infoPtr);
|
||||
*infoPtr = newReplayGainInfo();
|
||||
|
||||
while(*comments) {
|
||||
if((temp = ogg_parseComment(*comments,"replaygain_track_gain")))
|
||||
{
|
||||
trackGain = atof(temp);
|
||||
trackGainFound = 1;
|
||||
(*infoPtr)->trackGain = atof(temp);
|
||||
found = 1;
|
||||
}
|
||||
else if((temp = ogg_parseComment(*comments,
|
||||
"replaygain_album_gain")))
|
||||
{
|
||||
albumGain = atof(temp);
|
||||
albumGainFound = 1;
|
||||
(*infoPtr)->albumGain = atof(temp);
|
||||
found = 1;
|
||||
}
|
||||
else if((temp = ogg_parseComment(*comments,
|
||||
"replaygain_track_peak")))
|
||||
{
|
||||
trackPeak = atof(temp);
|
||||
(*infoPtr)->trackPeak = atof(temp);
|
||||
found = 1;
|
||||
}
|
||||
else if((temp = ogg_parseComment(*comments,
|
||||
"replaygain_album_peak")))
|
||||
{
|
||||
albumPeak = atof(temp);
|
||||
(*infoPtr)->albumPeak = atof(temp);
|
||||
found = 1;
|
||||
}
|
||||
|
||||
comments++;
|
||||
}
|
||||
|
||||
switch(replayGainState) {
|
||||
case REPLAYGAIN_ALBUM:
|
||||
if(albumGainFound) {
|
||||
return computeReplayGainScale(albumGain,albumPeak);
|
||||
}
|
||||
else if(trackGainFound) {
|
||||
return computeReplayGainScale(trackGain,trackPeak);
|
||||
}
|
||||
case REPLAYGAIN_TRACK:
|
||||
if(trackGainFound) {
|
||||
return computeReplayGainScale(trackGain,trackPeak);
|
||||
}
|
||||
else if(albumGainFound) {
|
||||
return computeReplayGainScale(albumGain,albumPeak);
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0;
|
||||
if(!found) {
|
||||
freeReplayGainInfo(*infoPtr);
|
||||
*infoPtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
MpdTag * oggCommentsParse(char ** comments) {
|
||||
@@ -248,7 +231,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
||||
int chunkpos = 0;
|
||||
long bitRate = 0;
|
||||
long test;
|
||||
float replayGainScale = 1.0;
|
||||
ReplayGainInfo * replayGainInfo = NULL;
|
||||
char ** comments;
|
||||
|
||||
data.inStream = inStream;
|
||||
@@ -304,7 +287,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
||||
comments = ov_comment(&vf, -1)->user_comments;
|
||||
putOggCommentsIntoOutputBuffer(cb, inStream->metaName,
|
||||
comments);
|
||||
replayGainScale = ogg_getReplayGainScale(comments);
|
||||
ogg_getReplayGainInfo(comments, &replayGainInfo);
|
||||
}
|
||||
|
||||
prev_section = current_section;
|
||||
@@ -321,14 +304,13 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
||||
if((test = ov_bitrate_instant(&vf))>0) {
|
||||
bitRate = test/1000;
|
||||
}
|
||||
doReplayGain(chunk,chunkpos,&(dc->audioFormat),
|
||||
replayGainScale);
|
||||
sendDataToOutputBuffer(cb, inStream, dc,
|
||||
inStream->seekable,
|
||||
chunk, chunkpos,
|
||||
ov_pcm_tell(&vf)/
|
||||
dc->audioFormat.sampleRate,
|
||||
bitRate);
|
||||
bitRate,
|
||||
replayGainInfo);
|
||||
chunkpos = 0;
|
||||
if(dc->stop) break;
|
||||
}
|
||||
@@ -337,9 +319,11 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
||||
if(!dc->stop && chunkpos > 0) {
|
||||
sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable,
|
||||
chunk, chunkpos,
|
||||
ov_time_tell(&vf), bitRate);
|
||||
ov_time_tell(&vf), bitRate, replayGainInfo);
|
||||
}
|
||||
|
||||
if(replayGainInfo) freeReplayGainInfo(replayGainInfo);
|
||||
|
||||
ov_clear(&vf);
|
||||
|
||||
flushOutputBuffer(cb);
|
||||
|
||||
Reference in New Issue
Block a user