Fix: don't chop off the first 26ms of each MP3 (but don't change sync,
either).
This commit is contained in:
@@ -520,7 +520,7 @@ void RageSound::StopPlaying()
|
|||||||
if(!playing)
|
if(!playing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stopped_position = GetPositionSeconds();
|
stopped_position = GetPositionSecondsInternal();
|
||||||
|
|
||||||
/* Tell the sound manager to stop mixing this sound. */
|
/* Tell the sound manager to stop mixing this sound. */
|
||||||
SOUNDMAN->StopMixing(this);
|
SOUNDMAN->StopMixing(this);
|
||||||
@@ -555,7 +555,8 @@ float RageSound::GetLengthSeconds()
|
|||||||
return len / 1000.f; /* ms -> secs */
|
return len / 1000.f; /* ms -> secs */
|
||||||
}
|
}
|
||||||
|
|
||||||
float RageSound::GetPositionSeconds() const
|
/* Get the position, not counting GetOffsetFix. */
|
||||||
|
float RageSound::GetPositionSecondsInternal() const
|
||||||
{
|
{
|
||||||
LockMut(SOUNDMAN->lock);
|
LockMut(SOUNDMAN->lock);
|
||||||
|
|
||||||
@@ -624,6 +625,13 @@ float RageSound::GetPositionSeconds() const
|
|||||||
return GetPlaybackRate() * closest_position / float(samplerate());
|
return GetPlaybackRate() * closest_position / float(samplerate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float RageSound::GetPositionSeconds() const
|
||||||
|
{
|
||||||
|
LOG->Trace("XXX fix %f", Sample->GetOffsetFix());
|
||||||
|
return GetPositionSecondsInternal() + Sample->GetOffsetFix();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool RageSound::SetPositionSeconds( float fSeconds )
|
bool RageSound::SetPositionSeconds( float fSeconds )
|
||||||
{
|
{
|
||||||
return SetPositionSamples( fSeconds == -1? -1: int(fSeconds * samplerate()) );
|
return SetPositionSamples( fSeconds == -1? -1: int(fSeconds * samplerate()) );
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ private:
|
|||||||
|
|
||||||
CString error;
|
CString error;
|
||||||
|
|
||||||
|
float GetPositionSecondsInternal() const;
|
||||||
bool SetPositionSamples( int samples = -1 );
|
bool SetPositionSamples( int samples = -1 );
|
||||||
int GetData(char *buffer, int size);
|
int GetData(char *buffer, int size);
|
||||||
void Fail(CString reason);
|
void Fail(CString reason);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ protected:
|
|||||||
void SetError(string e) const { error = e; }
|
void SetError(string e) const { error = e; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual float GetOffsetFix() const { return 0; }
|
||||||
|
|
||||||
virtual int GetLength() const = 0; /* ms */
|
virtual int GetLength() const = 0; /* ms */
|
||||||
virtual int GetLength_Fast() const { return GetLength(); } /* ms */
|
virtual int GetLength_Fast() const { return GetLength(); } /* ms */
|
||||||
virtual int SetPosition_Accurate(int ms) = 0;
|
virtual int SetPosition_Accurate(int ms) = 0;
|
||||||
|
|||||||
@@ -604,12 +604,24 @@ SoundReader_FileReader::OpenResult RageSoundReader_MP3::Open( CString filename_
|
|||||||
|
|
||||||
SampleRate = mad->Frame.header.samplerate;
|
SampleRate = mad->Frame.header.samplerate;
|
||||||
mad->framelength = mad->Frame.header.duration;
|
mad->framelength = mad->Frame.header.duration;
|
||||||
this->Channels = 0;
|
this->Channels = MAD_NCHANNELS( &mad->Frame.header );
|
||||||
|
|
||||||
/* Since we've already decoded a frame, just synth it instead of rewinding
|
/* Since we've already decoded a frame, just synth it instead of rewinding
|
||||||
* the stream. */
|
* the stream. */
|
||||||
synth_output();
|
synth_output();
|
||||||
this->Channels = MAD_NCHANNELS( &mad->Frame.header );
|
|
||||||
|
/*
|
||||||
|
* Hack: Old code was setting Channels = 0 before synth_output. This caused
|
||||||
|
* the first synthed frame to not be written to the output buffer, offsetting
|
||||||
|
* the whole song by a buffer. On one test song, it was 1152/44100, or 26ms.
|
||||||
|
* This affects all MP3s. We can't leave the bug in, since we need to handle
|
||||||
|
* seeks properly, too. So, let's make the offset to fix seeks available.
|
||||||
|
*
|
||||||
|
* This is negative: if we have 26ms of extra data, then song offsets are
|
||||||
|
* fixed by subtracting 26ms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
this->OffsetFix = - (float) mad->Synth.pcm.length / mad->Frame.header.samplerate;
|
||||||
|
|
||||||
if(mad->length == -1)
|
if(mad->length == -1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class RageSoundReader_MP3: public SoundReader_FileReader
|
|||||||
public:
|
public:
|
||||||
int SampleRate;
|
int SampleRate;
|
||||||
int Channels;
|
int Channels;
|
||||||
|
float OffsetFix;
|
||||||
|
|
||||||
CString filename;
|
CString filename;
|
||||||
FILE *rw;
|
FILE *rw;
|
||||||
@@ -40,6 +41,8 @@ public:
|
|||||||
int SetPosition_Fast(int ms);
|
int SetPosition_Fast(int ms);
|
||||||
int Read(char *buf, unsigned len);
|
int Read(char *buf, unsigned len);
|
||||||
int GetSampleRate() const { return SampleRate; }
|
int GetSampleRate() const { return SampleRate; }
|
||||||
|
float GetOffsetFix() const { return OffsetFix; }
|
||||||
|
|
||||||
RageSoundReader_MP3();
|
RageSoundReader_MP3();
|
||||||
~RageSoundReader_MP3();
|
~RageSoundReader_MP3();
|
||||||
RageSoundReader_MP3( const RageSoundReader_MP3 & ); /* not defined; don't use */
|
RageSoundReader_MP3( const RageSoundReader_MP3 & ); /* not defined; don't use */
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ bool SoundReader_Preload::Open(SoundReader *source)
|
|||||||
{
|
{
|
||||||
ASSERT(source);
|
ASSERT(source);
|
||||||
samplerate = source->GetSampleRate();
|
samplerate = source->GetSampleRate();
|
||||||
|
OffsetFix = source->GetOffsetFix(); // propagate upwards
|
||||||
|
|
||||||
/* Check the length, and see if we think it'll fit in the buffer. */
|
/* Check the length, and see if we think it'll fit in the buffer. */
|
||||||
int len = source->GetLength_Fast();
|
int len = source->GetLength_Fast();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class SoundReader_Preload: public SoundReader {
|
|||||||
int total_samples() const;
|
int total_samples() const;
|
||||||
|
|
||||||
int samplerate;
|
int samplerate;
|
||||||
|
float OffsetFix;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Return true if the sound has been preloaded, in which case source will
|
/* Return true if the sound has been preloaded, in which case source will
|
||||||
@@ -41,6 +42,7 @@ public:
|
|||||||
int SetPosition_Fast(int ms);
|
int SetPosition_Fast(int ms);
|
||||||
int Read(char *buf, unsigned len);
|
int Read(char *buf, unsigned len);
|
||||||
int GetSampleRate() const { return samplerate; }
|
int GetSampleRate() const { return samplerate; }
|
||||||
|
float GetOffsetFix() const { return OffsetFix; }
|
||||||
|
|
||||||
SoundReader *Copy() const;
|
SoundReader *Copy() const;
|
||||||
~SoundReader_Preload() { }
|
~SoundReader_Preload() { }
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public:
|
|||||||
RageSoundReader_Resample_Fast();
|
RageSoundReader_Resample_Fast();
|
||||||
virtual ~RageSoundReader_Resample_Fast();
|
virtual ~RageSoundReader_Resample_Fast();
|
||||||
SoundReader *Copy() const;
|
SoundReader *Copy() const;
|
||||||
|
float GetOffsetFix() const { return source->GetOffsetFix(); }
|
||||||
|
|
||||||
/* Change the actual sample rate of a sound. */
|
/* Change the actual sample rate of a sound. */
|
||||||
void SetSampleRate(int hz);
|
void SetSampleRate(int hz);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
RageSoundReader_Resample_Good();
|
RageSoundReader_Resample_Good();
|
||||||
virtual ~RageSoundReader_Resample_Good();
|
virtual ~RageSoundReader_Resample_Good();
|
||||||
SoundReader *Copy() const;
|
SoundReader *Copy() const;
|
||||||
|
float GetOffsetFix() const { return source->GetOffsetFix(); }
|
||||||
|
|
||||||
/* Change the actual sample rate of a sound. */
|
/* Change the actual sample rate of a sound. */
|
||||||
void SetSampleRate( int hz );
|
void SetSampleRate( int hz );
|
||||||
|
|||||||
Reference in New Issue
Block a user