Skip to content

Commit

Permalink
Fix possible audio corruption.
Browse files Browse the repository at this point in the history
Under some circumstances, audio already played could be heard again. This was the result of an incorrect audio circular buffer pointer calculation
  • Loading branch information
jyavenard committed Oct 6, 2011
1 parent 19b31f3 commit 35468d7
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 20 deletions.
33 changes: 17 additions & 16 deletions mythtv/libs/libmyth/audiooutputbase.cpp
Expand Up @@ -959,7 +959,7 @@ int AudioOutputBase::CheckFreeSpace(int &frames)
* Returns the number of frames written, which may be less than requested
* if the upmixer buffered some (or all) of them
*/
int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, uint &org_waud)
{
int len = CheckFreeSpace(frames);
int bdiff = kAudioRingBufferSize - org_waud;
Expand All @@ -978,7 +978,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
}
if (num > 0)
memcpy(WPOS, buffer + off, num);
org_waud += num;
org_waud = (org_waud + num) % kAudioRingBufferSize;
return len;
}

Expand All @@ -996,7 +996,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
if (frames > 0)
AudioOutputUtil::MonoToStereo(WPOS, buffer + off, frames);

org_waud += frames * bpf;
org_waud = (org_waud + frames * bpf) % kAudioRingBufferSize;
return len;
}

Expand Down Expand Up @@ -1031,7 +1031,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
if (nFrames > 0)
upmixer->receiveFrames((float *)(WPOS), nFrames);

org_waud += nFrames * bpf;
org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
}
return len;
}
Expand All @@ -1044,12 +1044,13 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
int64_t timecode)
{
int org_waud = waud, afree = audiofree();
int frames = in_frames;
void *buffer = in_buffer;
int bpf = bytes_per_frame, len = frames * source_bytes_per_frame;
int used = kAudioRingBufferSize - afree;
bool music = false;
uint org_waud = waud;
int afree = audiofree();
int frames = in_frames;
void *buffer = in_buffer;
int bpf = bytes_per_frame, len = frames * source_bytes_per_frame;
int used = kAudioRingBufferSize - afree;
bool music = false;
int bdiff;

VBAUDIOTS(QString("AddFrames frames=%1, bytes=%2, used=%3, free=%4, "
Expand Down Expand Up @@ -1202,7 +1203,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
nFrames = pSoundStretch->receiveSamples((STST *)(WPOS),
nFrames);

org_waud += nFrames * bpf;
org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
}

if (internal_vol && SWVolume())
Expand All @@ -1220,7 +1221,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
if (num > 0)
AudioOutputUtil::AdjustVolume(WPOS, num, volume,
music, needs_upmix && upmixer);
org_waud += num;
org_waud = (org_waud + num) % kAudioRingBufferSize;
}

if (encoder)
Expand Down Expand Up @@ -1253,7 +1254,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
else
{
to_get = encoder->Encode(WPOS, len, processing);
org_waud += len;
org_waud = (org_waud + len) % kAudioRingBufferSize;
}

bdiff = kAudioRingBufferSize - org_waud2;
Expand All @@ -1266,7 +1267,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
if (to_get > 0)
encoder->GetFrames(audiobuffer + org_waud2, to_get);

org_waud2 += to_get;
org_waud2 = (org_waud2 + to_get) % kAudioRingBufferSize;
}
while (remaining > 0);
org_waud = org_waud2;
Expand Down Expand Up @@ -1387,7 +1388,7 @@ void AudioOutputBase::OutputAudioLoop(void)
// delay setting raud until after phys buffer is filled
// so GetAudiotime will be accurate without locking
reset_active.TestAndDeref();
int next_raud = raud;
volatile uint next_raud = raud;
if (GetAudioData(fragment, fragment_size, true, &next_raud))
{
if (!reset_active.TestAndDeref())
Expand Down Expand Up @@ -1419,7 +1420,7 @@ void AudioOutputBase::OutputAudioLoop(void)
* available. Returns the number of bytes copied.
*/
int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer,
int *local_raud)
volatile uint *local_raud)
{

#define LRPOS audiobuffer + *local_raud
Expand Down
9 changes: 5 additions & 4 deletions mythtv/libs/libmyth/audiooutputbase.h
Expand Up @@ -99,7 +99,7 @@ class AudioOutputBase : public AudioOutput, public QThread
static const uint kAudioSRCInputSize = 32768;

/// Audio Buffer Size -- should be divisible by 32,24,16,12,10,8,6,4,2..
static const uint kAudioRingBufferSize = 3072000;
static const uint kAudioRingBufferSize = 3072000u;

protected:
// Following function must be called from subclass constructor
Expand All @@ -120,7 +120,8 @@ class AudioOutputBase : public AudioOutput, public QThread
virtual bool StartOutputThread(void);
virtual void StopOutputThread(void);

int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer, int *local_raud = NULL);
int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer,
volatile uint *local_raud = NULL);

void OutputAudioLoop(void);

Expand Down Expand Up @@ -169,7 +170,7 @@ class AudioOutputBase : public AudioOutput, public QThread
int src_quality;

private:
int CopyWithUpmix(char *buffer, int frames, int &org_waud);
int CopyWithUpmix(char *buffer, int frames, uint &org_waud);
void SetAudiotime(int frames, int64_t timecode);
AudioOutputSettings *output_settingsraw;
AudioOutputSettings *output_settings;
Expand Down Expand Up @@ -208,7 +209,7 @@ class AudioOutputBase : public AudioOutput, public QThread
int64_t audiotime;

/* Audio circular buffer */
int raud, waud; /* read and write positions */
volatile uint raud, waud; /* read and write positions */
// timecode of audio most recently placed into buffer
int64_t audbuf_timecode;
AsyncLooseLock reset_active;
Expand Down

0 comments on commit 35468d7

Please sign in to comment.