aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarren Dukes <warren.dukes@gmail.com>2004-11-02 19:56:59 +0000
committerWarren Dukes <warren.dukes@gmail.com>2004-11-02 19:56:59 +0000
commit54679d9028117360e50a85a1f4b4f376f13ad6a3 (patch)
treee23dbf750251f57a6f836ca65693628916eca006
parent1d105d126e84f80b28bc60a742e2631a4227a101 (diff)
downloadmpd-54679d9028117360e50a85a1f4b4f376f13ad6a3.tar.gz
mpd-54679d9028117360e50a85a1f4b4f376f13ad6a3.tar.xz
mpd-54679d9028117360e50a85a1f4b4f376f13ad6a3.zip
rewrite replaygain code, needs testing
git-svn-id: https://svn.musicpd.org/mpd/trunk@2482 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to '')
-rw-r--r--TODO4
-rw-r--r--src/inputPlugins/aac_plugin.c2
-rw-r--r--src/inputPlugins/audiofile_plugin.c3
-rw-r--r--src/inputPlugins/flac_plugin.c50
-rw-r--r--src/inputPlugins/mod_plugin.c2
-rw-r--r--src/inputPlugins/mp3_plugin.c6
-rw-r--r--src/inputPlugins/mp4_plugin.c2
-rw-r--r--src/inputPlugins/ogg_plugin.c62
-rw-r--r--src/outputBuffer.c5
-rw-r--r--src/outputBuffer.h14
-rw-r--r--src/replayGain.c58
-rw-r--r--src/replayGain.h20
12 files changed, 133 insertions, 95 deletions
diff --git a/TODO b/TODO
index 72a7b8647..0e824dd99 100644
--- a/TODO
+++ b/TODO
@@ -7,10 +7,6 @@
*) Steal resampling code from ices (i think this code works only for 16-bit)
*) Rewrite replaygain stuff:
- *) Replay gain struct with album and track gain's and peak's
- *) Pass these to replaygain function
- *) Don't have deocder plugins inquire weather or not to use replaygain,
- they should just parse tags and pass these to replaygain func
*) If replaygain tag info present, average the replaygain gain's
and peak's on the fly
*) If NULL replaygain struct, then use the average replaygain gains
diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c
index 9f78fc2a1..1d844426a 100644
--- a/src/inputPlugins/aac_plugin.c
+++ b/src/inputPlugins/aac_plugin.c
@@ -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;
diff --git a/src/inputPlugins/audiofile_plugin.c b/src/inputPlugins/audiofile_plugin.c
index 818ba553e..0c205888d 100644
--- a/src/inputPlugins/audiofile_plugin.c
+++ b/src/inputPlugins/audiofile_plugin.c
@@ -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;
}
}
diff --git a/src/inputPlugins/flac_plugin.c b/src/inputPlugins/flac_plugin.c
index 1adf5a349..d038f1418 100644
--- a/src/inputPlugins/flac_plugin.c
+++ b/src/inputPlugins/flac_plugin.c
@@ -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;
diff --git a/src/inputPlugins/mod_plugin.c b/src/inputPlugins/mod_plugin.c
index 766c38658..2a03cc404 100644
--- a/src/inputPlugins/mod_plugin.c
+++ b/src/inputPlugins/mod_plugin.c
@@ -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);
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index db5756b95..ab204ffa9 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -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);
diff --git a/src/inputPlugins/mp4_plugin.c b/src/inputPlugins/mp4_plugin.c
index 982ea3ea2..66d5600b4 100644
--- a/src/inputPlugins/mp4_plugin.c
+++ b/src/inputPlugins/mp4_plugin.c
@@ -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;
diff --git a/src/inputPlugins/ogg_plugin.c b/src/inputPlugins/ogg_plugin.c
index 5d461586e..da08cb2e2 100644
--- a/src/inputPlugins/ogg_plugin.c
+++ b/src/inputPlugins/ogg_plugin.c
@@ -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);
diff --git a/src/outputBuffer.c b/src/outputBuffer.c
index cd7336a8b..463eeef79 100644
--- a/src/outputBuffer.c
+++ b/src/outputBuffer.c
@@ -64,7 +64,8 @@ void flushOutputBuffer(OutputBuffer * cb) {
int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
DecoderControl * dc, int seekable, char * dataIn,
- long dataInLen, float time, mpd_uint16 bitRate)
+ long dataInLen, float time, mpd_uint16 bitRate,
+ ReplayGainInfo * replayGainInfo)
{
mpd_uint16 dataToSend;
mpd_uint16 chunkLeft;
@@ -91,6 +92,8 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
&(cb->audioFormat),data);
}
+ doReplayGain(replayGainInfo, data, datalen, &cb->audioFormat);
+
while(datalen) {
if(currentChunk != cb->end) {
int next = cb->end+1;
diff --git a/src/outputBuffer.h b/src/outputBuffer.h
index cec077542..23b49ef5b 100644
--- a/src/outputBuffer.h
+++ b/src/outputBuffer.h
@@ -24,6 +24,7 @@
#include "audio.h"
#include "inputStream.h"
#include "metadataChunk.h"
+#include "replayGain.h"
#define OUTPUT_BUFFER_DC_STOP -1
#define OUTPUT_BUFFER_DC_SEEK -2
@@ -50,9 +51,16 @@ void flushOutputBuffer(OutputBuffer * cb);
/* we send inStream for buffering the inputStream while waiting to
send the next chunk */
-int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
- DecoderControl * dc, int seekable, char * data, long datalen,
- float time, mpd_uint16 bitRate);
+int sendDataToOutputBuffer(
+ OutputBuffer * cb,
+ InputStream * inStream,
+ DecoderControl * dc,
+ int seekable,
+ char * data,
+ long datalen,
+ float time,
+ mpd_uint16 bitRate,
+ ReplayGainInfo * replayGainInfo);
int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag);
diff --git a/src/replayGain.c b/src/replayGain.c
index 4788d7d95..138d3a68b 100644
--- a/src/replayGain.c
+++ b/src/replayGain.c
@@ -71,11 +71,7 @@ void initReplayGainState() {
}
}
-int getReplayGainState() {
- return replayGainState;
-}
-
-float computeReplayGainScale(float gain, float peak) {
+static float computeReplayGainScale(float gain, float peak) {
float scale;
if(gain == 0.0) return(1);
@@ -89,14 +85,55 @@ float computeReplayGainScale(float gain, float peak) {
return(scale);
}
-void doReplayGain(char * buffer, int bufferSize, AudioFormat * format,
- float scale)
+ReplayGainInfo * newReplayGainInfo() {
+ ReplayGainInfo * ret = malloc(sizeof(ReplayGainInfo));
+
+ ret->albumGain = 0.0;
+ ret->albumPeak = 1.0;
+
+ ret->trackGain = 0.0;
+ ret->trackPeak = 1.0;
+
+ /* set to -1 so that we know in doReplayGain to compute the scale */
+ ret->scale = -1.0;
+
+ return ret;
+}
+
+void freeReplayGainInfo(ReplayGainInfo * info) {
+ free(info);
+}
+
+void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize,
+ AudioFormat * format)
{
- mpd_sint16 * buffer16 = (mpd_sint16 *)buffer;
- mpd_sint8 * buffer8 = (mpd_sint8 *)buffer;
+ mpd_sint16 * buffer16;
+ mpd_sint8 * buffer8;
mpd_sint32 temp32;
+ float scale;
+
+ if(replayGainState == REPLAYGAIN_OFF || !info) return;
+
+ if(info->scale < 0) {
+ switch(replayGainState) {
+ case REPLAYGAIN_TRACK:
+ info->scale = computeReplayGainScale(info->trackGain,
+ info->trackPeak);
+ break;
+ default:
+ info->scale = computeReplayGainScale(info->albumGain,
+ info->albumPeak);
+ break;
+ }
+ }
+
+ if(info->scale <= 1.01 && info->scale >= 0.99) return;
+
+ buffer16 = (mpd_sint16 *)buffer;
+ buffer8 = (mpd_sint8 *)buffer;
+
+ scale = info->scale;
- if(scale == 1.0) return;
switch(format->bits) {
case 16:
while(bufferSize > 0){
@@ -122,4 +159,3 @@ void doReplayGain(char * buffer, int bufferSize, AudioFormat * format,
ERROR("%i bits not supported by doReplaygain!\n", format->bits);
}
}
-/* End of added code */
diff --git a/src/replayGain.h b/src/replayGain.h
index 5d8ee7b24..112034fbe 100644
--- a/src/replayGain.h
+++ b/src/replayGain.h
@@ -26,13 +26,23 @@
#define REPLAYGAIN_TRACK 1
#define REPLAYGAIN_ALBUM 2
-void initReplayGainState();
+typedef struct _ReplayGainInfo {
+ float albumGain;
+ float albumPeak;
+ float trackGain;
+ float trackPeak;
+
+ /* used internally by mpd, to mess with it*/
+ float scale;
+} ReplayGainInfo;
-int getReplayGainState();
+ReplayGainInfo * newReplayGainInfo();
-float computeReplayGainScale(float gain, float peak);
+void freeReplayGainInfo(ReplayGainInfo * info);
+
+void initReplayGainState();
-void doReplayGain(char * buffer, int bufferSize, AudioFormat * format,
- float scale);
+void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize,
+ AudioFormat * format);
#endif