* Use TimeComputer to get smoother performance times.

* SetParameterValue(): Don't do anything, if the new output frequency value
  is the same as before. This avoids hickups when switching between the pages
  in the Media preflet.
* _FillNextBuffer(): Compare BBuffer and stream buffer size. They might
  differ directly after setting another output frequency, which could cause
  a crash.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34683 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-12-16 20:13:14 +00:00
parent cb00754227
commit 9c3ad4fbb0
2 changed files with 25 additions and 28 deletions
@@ -1408,6 +1408,9 @@ MultiAudioNode::SetParameterValue(int32 id, bigtime_t performanceTime,
return; return;
memcpy(&rate, value, sizeof(rate)); memcpy(&rate, value, sizeof(rate));
if (rate == fOutputPreferredFormat.u.raw_audio.frame_rate)
return;
// create a cookie RequestCompleted() can get the old frame rate from, // create a cookie RequestCompleted() can get the old frame rate from,
// if anything goes wrong // if anything goes wrong
OutputFrameRateChangeCookie* cookie OutputFrameRateChangeCookie* cookie
@@ -1665,8 +1668,12 @@ MultiAudioNode::_RunThread()
bufferInfo.playback_buffer_cycle = 0; bufferInfo.playback_buffer_cycle = 0;
bufferInfo.record_buffer_cycle = 0; bufferInfo.record_buffer_cycle = 0;
// reset the info for the performance time computation // init the performance time computation
fResetPerformanceTimeBase = true; {
BAutolock locker(fBufferLock);
fTimeComputer.Init(fOutputPreferredFormat.u.raw_audio.frame_rate,
system_time());
}
while (true) { while (true) {
// TODO: why this semaphore?? // TODO: why this semaphore??
@@ -1862,6 +1869,14 @@ MultiAudioNode::_FillNextBuffer(node_input& input, BBuffer* buffer)
uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size; uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size;
if (buffer->SizeUsed()
/ (input.fInput.format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK)
/ input.fInput.format.u.raw_audio.channel_count != bufferSize) {
_WriteZeros(input, input.fBufferCycle);
return;
}
switch (input.fInput.format.u.raw_audio.format) { switch (input.fInput.format.u.raw_audio.format) {
case media_raw_audio_format::B_AUDIO_FLOAT: case media_raw_audio_format::B_AUDIO_FLOAT:
switch (input.fFormat.u.raw_audio.format) { switch (input.fFormat.u.raw_audio.format) {
@@ -2128,27 +2143,9 @@ MultiAudioNode::_UpdateTimeSource(multi_buffer_info& info,
if (!fTimeSourceStarted || oldInfo.played_real_time == 0) if (!fTimeSourceStarted || oldInfo.played_real_time == 0)
return; return;
if (fResetPerformanceTimeBase) { fTimeComputer.AddTimeStamp(info.played_real_time, info.played_frames_count);
fPerformanceTimeBase = info.played_real_time; PublishTime(fTimeComputer.PerformanceTime(), fTimeComputer.RealTime(),
fPerformanceTimeBaseFrames = info.played_frames_count; fTimeComputer.Drift());
fResetPerformanceTimeBase = false;
return;
}
double usecsPerFrame = 1000000 / input.fInput.format.u.raw_audio.frame_rate;
uint64 frameCount = info.played_frames_count
- fPerformanceTimeBaseFrames;
uint64 oldFrameCount = oldInfo.played_frames_count
- fPerformanceTimeBaseFrames;
bigtime_t performanceTime = (bigtime_t)(frameCount * usecsPerFrame)
+ fPerformanceTimeBase;
bigtime_t realTime = info.played_real_time;
float drift = ((frameCount - oldFrameCount) * usecsPerFrame)
/ (info.played_real_time - oldInfo.played_real_time);
PublishTime(performanceTime, realTime, drift);
//PRINT(("_UpdateTimeSource() perf_time : %lli, real_time : %lli, drift : %f\n", performanceTime, realTime, drift));
} }
@@ -2351,7 +2348,7 @@ MultiAudioNode::_SetNodeInputFrameRate(float frameRate)
} }
// make sure the time base is reset // make sure the time base is reset
fResetPerformanceTimeBase = true; fTimeComputer.SetFrameRate(frameRate);
// update internal latency // update internal latency
_UpdateInternalLatency(fOutputPreferredFormat); _UpdateInternalLatency(fOutputPreferredFormat);
@@ -2363,7 +2360,7 @@ MultiAudioNode::_SetNodeInputFrameRate(float frameRate)
void void
MultiAudioNode::_UpdateInternalLatency(const media_format& format) MultiAudioNode::_UpdateInternalLatency(const media_format& format)
{ {
// use one buffer length latency // use half a buffer length latency
fInternalLatency = format.u.raw_audio.buffer_size * 10000 / 2 fInternalLatency = format.u.raw_audio.buffer_size * 10000 / 2
/ ((format.u.raw_audio.format / ((format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK) & media_raw_audio_format::B_AUDIO_SIZE_MASK)
@@ -19,6 +19,8 @@
#include "hmulti_audio.h" #include "hmulti_audio.h"
#include "MultiAudioDevice.h" #include "MultiAudioDevice.h"
#include "TimeComputer.h"
class BDiscreteParameter; class BDiscreteParameter;
class BParameterGroup; class BParameterGroup;
@@ -205,9 +207,7 @@ private:
BLocker fBufferLock; BLocker fBufferLock;
BList fInputs; BList fInputs;
bool fResetPerformanceTimeBase; TimeComputer fTimeComputer;
bigtime_t fPerformanceTimeBase;
uint64 fPerformanceTimeBaseFrames;
bigtime_t fLatency; bigtime_t fLatency;
BList fOutputs; BList fOutputs;