* 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:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user