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:
4
TODO
4
TODO
@@ -7,10 +7,6 @@
|
|||||||
*) Steal resampling code from ices (i think this code works only for 16-bit)
|
*) Steal resampling code from ices (i think this code works only for 16-bit)
|
||||||
|
|
||||||
*) Rewrite replaygain stuff:
|
*) 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
|
*) If replaygain tag info present, average the replaygain gain's
|
||||||
and peak's on the fly
|
and peak's on the fly
|
||||||
*) If NULL replaygain struct, then use the average replaygain gains
|
*) If NULL replaygain struct, then use the average replaygain gains
|
||||||
|
@@ -362,7 +362,7 @@ int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
|||||||
sampleBufferLen = sampleCount*2;
|
sampleBufferLen = sampleCount*2;
|
||||||
|
|
||||||
sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer,
|
sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer,
|
||||||
sampleBufferLen, time, bitRate);
|
sampleBufferLen, time, bitRate, NULL);
|
||||||
if(dc->seek) {
|
if(dc->seek) {
|
||||||
dc->seekError = 1;
|
dc->seekError = 1;
|
||||||
dc->seek = 0;
|
dc->seek = 0;
|
||||||
|
@@ -116,7 +116,8 @@ int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
|||||||
ret*fs,
|
ret*fs,
|
||||||
(float)current /
|
(float)current /
|
||||||
(float)dc->audioFormat.sampleRate,
|
(float)dc->audioFormat.sampleRate,
|
||||||
bitRate);
|
bitRate,
|
||||||
|
NULL);
|
||||||
if(dc->stop) break;
|
if(dc->stop) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,8 +44,8 @@ typedef struct {
|
|||||||
OutputBuffer * cb;
|
OutputBuffer * cb;
|
||||||
DecoderControl * dc;
|
DecoderControl * dc;
|
||||||
InputStream inStream;
|
InputStream inStream;
|
||||||
float replayGainScale;
|
|
||||||
char * path;
|
char * path;
|
||||||
|
ReplayGainInfo * replayGainInfo;
|
||||||
} FlacData;
|
} FlacData;
|
||||||
|
|
||||||
/* this code is based on flac123, from flac-tools */
|
/* 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.bitRate = 0;
|
||||||
data.cb = cb;
|
data.cb = cb;
|
||||||
data.dc = dc;
|
data.dc = dc;
|
||||||
data.replayGainScale = 1.0;
|
data.replayGainInfo = NULL;
|
||||||
data.path = path;
|
data.path = path;
|
||||||
|
|
||||||
if(openInputStream(&(data.inStream), path)<0) {
|
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;
|
else dc->state = DECODE_STATE_STOP;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
if(data.replayGainInfo) freeReplayGainInfo(data.replayGainInfo);
|
||||||
|
|
||||||
if(streamOpen) closeInputStream(&(data.inStream));
|
if(streamOpen) closeInputStream(&(data.inStream));
|
||||||
|
|
||||||
if(flacDec) FLAC__seekable_stream_decoder_delete(flacDec);
|
if(flacDec) FLAC__seekable_stream_decoder_delete(flacDec);
|
||||||
@@ -338,30 +340,28 @@ int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block, char * cmnt,
|
|||||||
|
|
||||||
/* replaygain stuff by AliasMrJones */
|
/* replaygain stuff by AliasMrJones */
|
||||||
void flacParseReplayGain(const FLAC__StreamMetadata *block, FlacData * data) {
|
void flacParseReplayGain(const FLAC__StreamMetadata *block, FlacData * data) {
|
||||||
int found;
|
if(NULL == data->replayGainInfo) {
|
||||||
float gain = 0.0;
|
freeReplayGainInfo(data->replayGainInfo);
|
||||||
float peak = 0.0;
|
data->replayGainInfo = NULL;
|
||||||
int state = getReplayGainState();
|
}
|
||||||
|
|
||||||
if(state == REPLAYGAIN_OFF) return;
|
data->replayGainInfo = newReplayGainInfo();
|
||||||
|
|
||||||
found = flacFindVorbisCommentFloat(block,"replaygain_album_gain",&gain);
|
int found = 0;
|
||||||
if(found) {
|
|
||||||
flacFindVorbisCommentFloat(block,"replaygain_album_peak",
|
|
||||||
&peak);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!found || state == REPLAYGAIN_TRACK) {
|
found &= flacFindVorbisCommentFloat(block,"replaygain_album_gain",
|
||||||
found = flacFindVorbisCommentFloat(block,
|
&data->replayGainInfo->albumGain);
|
||||||
"replaygain_track_gain", &gain);
|
found &= flacFindVorbisCommentFloat(block,"replaygain_album_peak",
|
||||||
if(found) {
|
&data->replayGainInfo->albumPeak);
|
||||||
peak = 0.0;
|
found &= flacFindVorbisCommentFloat(block,"replaygain_track_gain",
|
||||||
flacFindVorbisCommentFloat(block,
|
&data->replayGainInfo->trackGain);
|
||||||
"replaygain_track_peak",&peak);
|
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,
|
void flacMetadata(const FLAC__SeekableStreamDecoder *dec,
|
||||||
@@ -391,11 +391,9 @@ void flacMetadata(const FLAC__SeekableStreamDecoder *dec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int flacSendChunk(FlacData * data) {
|
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,
|
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:
|
case OUTPUT_BUFFER_DC_STOP:
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -191,7 +191,7 @@ int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
|||||||
time += ret*secPerByte;
|
time += ret*secPerByte;
|
||||||
sendDataToOutputBuffer(cb, NULL, dc, 0,
|
sendDataToOutputBuffer(cb, NULL, dc, 0,
|
||||||
(char *)data->audio_buffer, ret, time,
|
(char *)data->audio_buffer, ret, time,
|
||||||
0);
|
0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
flushOutputBuffer(cb);
|
flushOutputBuffer(cb);
|
||||||
|
@@ -585,7 +585,8 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
|
|||||||
data->outputPtr-
|
data->outputPtr-
|
||||||
data->outputBuffer,
|
data->outputBuffer,
|
||||||
data->elapsedTime,
|
data->elapsedTime,
|
||||||
data->bitRate/1000);
|
data->bitRate/1000,
|
||||||
|
NULL);
|
||||||
if(ret == OUTPUT_BUFFER_DC_STOP) {
|
if(ret == OUTPUT_BUFFER_DC_STOP) {
|
||||||
data->flush = 0;
|
data->flush = 0;
|
||||||
return DECODE_BREAK;
|
return DECODE_BREAK;
|
||||||
@@ -710,7 +711,8 @@ int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) {
|
|||||||
data.inStream->seekable,
|
data.inStream->seekable,
|
||||||
data.outputBuffer,
|
data.outputBuffer,
|
||||||
data.outputPtr-data.outputBuffer,
|
data.outputPtr-data.outputBuffer,
|
||||||
data.elapsedTime,data.bitRate/1000);
|
data.elapsedTime,data.bitRate/1000,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeInputStream(inStream);
|
closeInputStream(inStream);
|
||||||
|
@@ -284,7 +284,7 @@ int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
|||||||
sampleBuffer+=offset*channels*2;
|
sampleBuffer+=offset*channels*2;
|
||||||
|
|
||||||
sendDataToOutputBuffer(cb, NULL, dc, 1, sampleBuffer,
|
sendDataToOutputBuffer(cb, NULL, dc, 1, sampleBuffer,
|
||||||
sampleBufferLen, time, bitRate);
|
sampleBufferLen, time, bitRate, NULL);
|
||||||
if(dc->stop) {
|
if(dc->stop) {
|
||||||
eof = 1;
|
eof = 1;
|
||||||
break;
|
break;
|
||||||
|
@@ -114,62 +114,45 @@ char * ogg_parseComment(char * comment, char * needle) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
float ogg_getReplayGainScale(char ** comments) {
|
void ogg_getReplayGainInfo(char ** comments, ReplayGainInfo ** infoPtr) {
|
||||||
int trackGainFound = 0;
|
|
||||||
int albumGainFound = 0;
|
|
||||||
float trackGain = 1.0;
|
|
||||||
float albumGain = 1.0;
|
|
||||||
float trackPeak = 0.0;
|
|
||||||
float albumPeak = 0.0;
|
|
||||||
char * temp;
|
char * temp;
|
||||||
int replayGainState = getReplayGainState();
|
int found = 0;
|
||||||
|
|
||||||
if(replayGainState == REPLAYGAIN_OFF) return 1.0;
|
if(*infoPtr) freeReplayGainInfo(*infoPtr);
|
||||||
|
*infoPtr = newReplayGainInfo();
|
||||||
|
|
||||||
while(*comments) {
|
while(*comments) {
|
||||||
if((temp = ogg_parseComment(*comments,"replaygain_track_gain")))
|
if((temp = ogg_parseComment(*comments,"replaygain_track_gain")))
|
||||||
{
|
{
|
||||||
trackGain = atof(temp);
|
(*infoPtr)->trackGain = atof(temp);
|
||||||
trackGainFound = 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
else if((temp = ogg_parseComment(*comments,
|
else if((temp = ogg_parseComment(*comments,
|
||||||
"replaygain_album_gain")))
|
"replaygain_album_gain")))
|
||||||
{
|
{
|
||||||
albumGain = atof(temp);
|
(*infoPtr)->albumGain = atof(temp);
|
||||||
albumGainFound = 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
else if((temp = ogg_parseComment(*comments,
|
else if((temp = ogg_parseComment(*comments,
|
||||||
"replaygain_track_peak")))
|
"replaygain_track_peak")))
|
||||||
{
|
{
|
||||||
trackPeak = atof(temp);
|
(*infoPtr)->trackPeak = atof(temp);
|
||||||
|
found = 1;
|
||||||
}
|
}
|
||||||
else if((temp = ogg_parseComment(*comments,
|
else if((temp = ogg_parseComment(*comments,
|
||||||
"replaygain_album_peak")))
|
"replaygain_album_peak")))
|
||||||
{
|
{
|
||||||
albumPeak = atof(temp);
|
(*infoPtr)->albumPeak = atof(temp);
|
||||||
|
found = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
comments++;
|
comments++;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(replayGainState) {
|
if(!found) {
|
||||||
case REPLAYGAIN_ALBUM:
|
freeReplayGainInfo(*infoPtr);
|
||||||
if(albumGainFound) {
|
*infoPtr = NULL;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MpdTag * oggCommentsParse(char ** comments) {
|
MpdTag * oggCommentsParse(char ** comments) {
|
||||||
@@ -248,7 +231,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
|||||||
int chunkpos = 0;
|
int chunkpos = 0;
|
||||||
long bitRate = 0;
|
long bitRate = 0;
|
||||||
long test;
|
long test;
|
||||||
float replayGainScale = 1.0;
|
ReplayGainInfo * replayGainInfo = NULL;
|
||||||
char ** comments;
|
char ** comments;
|
||||||
|
|
||||||
data.inStream = inStream;
|
data.inStream = inStream;
|
||||||
@@ -304,7 +287,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
|||||||
comments = ov_comment(&vf, -1)->user_comments;
|
comments = ov_comment(&vf, -1)->user_comments;
|
||||||
putOggCommentsIntoOutputBuffer(cb, inStream->metaName,
|
putOggCommentsIntoOutputBuffer(cb, inStream->metaName,
|
||||||
comments);
|
comments);
|
||||||
replayGainScale = ogg_getReplayGainScale(comments);
|
ogg_getReplayGainInfo(comments, &replayGainInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_section = current_section;
|
prev_section = current_section;
|
||||||
@@ -321,14 +304,13 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
|||||||
if((test = ov_bitrate_instant(&vf))>0) {
|
if((test = ov_bitrate_instant(&vf))>0) {
|
||||||
bitRate = test/1000;
|
bitRate = test/1000;
|
||||||
}
|
}
|
||||||
doReplayGain(chunk,chunkpos,&(dc->audioFormat),
|
|
||||||
replayGainScale);
|
|
||||||
sendDataToOutputBuffer(cb, inStream, dc,
|
sendDataToOutputBuffer(cb, inStream, dc,
|
||||||
inStream->seekable,
|
inStream->seekable,
|
||||||
chunk, chunkpos,
|
chunk, chunkpos,
|
||||||
ov_pcm_tell(&vf)/
|
ov_pcm_tell(&vf)/
|
||||||
dc->audioFormat.sampleRate,
|
dc->audioFormat.sampleRate,
|
||||||
bitRate);
|
bitRate,
|
||||||
|
replayGainInfo);
|
||||||
chunkpos = 0;
|
chunkpos = 0;
|
||||||
if(dc->stop) break;
|
if(dc->stop) break;
|
||||||
}
|
}
|
||||||
@@ -337,9 +319,11 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
|||||||
if(!dc->stop && chunkpos > 0) {
|
if(!dc->stop && chunkpos > 0) {
|
||||||
sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable,
|
sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable,
|
||||||
chunk, chunkpos,
|
chunk, chunkpos,
|
||||||
ov_time_tell(&vf), bitRate);
|
ov_time_tell(&vf), bitRate, replayGainInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(replayGainInfo) freeReplayGainInfo(replayGainInfo);
|
||||||
|
|
||||||
ov_clear(&vf);
|
ov_clear(&vf);
|
||||||
|
|
||||||
flushOutputBuffer(cb);
|
flushOutputBuffer(cb);
|
||||||
|
@@ -64,7 +64,8 @@ void flushOutputBuffer(OutputBuffer * cb) {
|
|||||||
|
|
||||||
int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
|
int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
|
||||||
DecoderControl * dc, int seekable, char * dataIn,
|
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 dataToSend;
|
||||||
mpd_uint16 chunkLeft;
|
mpd_uint16 chunkLeft;
|
||||||
@@ -91,6 +92,8 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
|
|||||||
&(cb->audioFormat),data);
|
&(cb->audioFormat),data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doReplayGain(replayGainInfo, data, datalen, &cb->audioFormat);
|
||||||
|
|
||||||
while(datalen) {
|
while(datalen) {
|
||||||
if(currentChunk != cb->end) {
|
if(currentChunk != cb->end) {
|
||||||
int next = cb->end+1;
|
int next = cb->end+1;
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "inputStream.h"
|
#include "inputStream.h"
|
||||||
#include "metadataChunk.h"
|
#include "metadataChunk.h"
|
||||||
|
#include "replayGain.h"
|
||||||
|
|
||||||
#define OUTPUT_BUFFER_DC_STOP -1
|
#define OUTPUT_BUFFER_DC_STOP -1
|
||||||
#define OUTPUT_BUFFER_DC_SEEK -2
|
#define OUTPUT_BUFFER_DC_SEEK -2
|
||||||
@@ -50,9 +51,16 @@ void flushOutputBuffer(OutputBuffer * cb);
|
|||||||
|
|
||||||
/* we send inStream for buffering the inputStream while waiting to
|
/* we send inStream for buffering the inputStream while waiting to
|
||||||
send the next chunk */
|
send the next chunk */
|
||||||
int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
|
int sendDataToOutputBuffer(
|
||||||
DecoderControl * dc, int seekable, char * data, long datalen,
|
OutputBuffer * cb,
|
||||||
float time, mpd_uint16 bitRate);
|
InputStream * inStream,
|
||||||
|
DecoderControl * dc,
|
||||||
|
int seekable,
|
||||||
|
char * data,
|
||||||
|
long datalen,
|
||||||
|
float time,
|
||||||
|
mpd_uint16 bitRate,
|
||||||
|
ReplayGainInfo * replayGainInfo);
|
||||||
|
|
||||||
int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag);
|
int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag);
|
||||||
|
|
||||||
|
@@ -71,11 +71,7 @@ void initReplayGainState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getReplayGainState() {
|
static float computeReplayGainScale(float gain, float peak) {
|
||||||
return replayGainState;
|
|
||||||
}
|
|
||||||
|
|
||||||
float computeReplayGainScale(float gain, float peak) {
|
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
if(gain == 0.0) return(1);
|
if(gain == 0.0) return(1);
|
||||||
@@ -89,14 +85,55 @@ float computeReplayGainScale(float gain, float peak) {
|
|||||||
return(scale);
|
return(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void doReplayGain(char * buffer, int bufferSize, AudioFormat * format,
|
ReplayGainInfo * newReplayGainInfo() {
|
||||||
float scale)
|
ReplayGainInfo * ret = malloc(sizeof(ReplayGainInfo));
|
||||||
{
|
|
||||||
mpd_sint16 * buffer16 = (mpd_sint16 *)buffer;
|
ret->albumGain = 0.0;
|
||||||
mpd_sint8 * buffer8 = (mpd_sint8 *)buffer;
|
ret->albumPeak = 1.0;
|
||||||
mpd_sint32 temp32;
|
|
||||||
|
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_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) {
|
switch(format->bits) {
|
||||||
case 16:
|
case 16:
|
||||||
while(bufferSize > 0){
|
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);
|
ERROR("%i bits not supported by doReplaygain!\n", format->bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* End of added code */
|
|
||||||
|
@@ -26,13 +26,23 @@
|
|||||||
#define REPLAYGAIN_TRACK 1
|
#define REPLAYGAIN_TRACK 1
|
||||||
#define REPLAYGAIN_ALBUM 2
|
#define REPLAYGAIN_ALBUM 2
|
||||||
|
|
||||||
|
typedef struct _ReplayGainInfo {
|
||||||
|
float albumGain;
|
||||||
|
float albumPeak;
|
||||||
|
float trackGain;
|
||||||
|
float trackPeak;
|
||||||
|
|
||||||
|
/* used internally by mpd, to mess with it*/
|
||||||
|
float scale;
|
||||||
|
} ReplayGainInfo;
|
||||||
|
|
||||||
|
ReplayGainInfo * newReplayGainInfo();
|
||||||
|
|
||||||
|
void freeReplayGainInfo(ReplayGainInfo * info);
|
||||||
|
|
||||||
void initReplayGainState();
|
void initReplayGainState();
|
||||||
|
|
||||||
int getReplayGainState();
|
void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize,
|
||||||
|
AudioFormat * format);
|
||||||
float computeReplayGainScale(float gain, float peak);
|
|
||||||
|
|
||||||
void doReplayGain(char * buffer, int bufferSize, AudioFormat * format,
|
|
||||||
float scale);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user