usb_audio: Clean up buffer management.
* Get rid of fPacketSize and use fSamplesCount in GetBuffers instead. * Clarify logic in _TransferCallback. * Properly multiply in kSamplesBufferCount to fAreaSize (this should be the only functional change in here.) The larger buffers (now similarly sized to HDA at least in the default cases of 44100 or 48000) seem to help with jittering and discontinuities, which are significantly reduced now, at least under emulation.
This commit is contained in:
@@ -31,7 +31,6 @@ Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
|
|||||||
fCurrentBuffer(0),
|
fCurrentBuffer(0),
|
||||||
fSamplesCount(0),
|
fSamplesCount(0),
|
||||||
fStartingFrame(0),
|
fStartingFrame(0),
|
||||||
fPacketSize(0),
|
|
||||||
fProcessedBuffers(0),
|
fProcessedBuffers(0),
|
||||||
fInsideNotify(0)
|
fInsideNotify(0)
|
||||||
{
|
{
|
||||||
@@ -164,11 +163,11 @@ Stream::_SetupBuffers()
|
|||||||
uint32 sampleSize = format->fNumChannels * format->fSubframeSize;
|
uint32 sampleSize = format->fNumChannels * format->fSubframeSize;
|
||||||
|
|
||||||
// data size pro 1 ms USB 1 frame or 1/8 ms USB 2 microframe
|
// data size pro 1 ms USB 1 frame or 1/8 ms USB 2 microframe
|
||||||
fPacketSize = samplingRate * sampleSize
|
size_t packetSize = samplingRate * sampleSize
|
||||||
/ (fDevice->fUSBVersion < 0x0200 ? 1000 : 8000);
|
/ (fDevice->fUSBVersion < 0x0200 ? 1000 : 8000);
|
||||||
TRACE(INF, "packetSize:%ld\n", fPacketSize);
|
TRACE(INF, "packetSize:%ld\n", packetSize);
|
||||||
|
|
||||||
if (fPacketSize == 0) {
|
if (packetSize == 0) {
|
||||||
TRACE(ERR, "computed packet size is 0!");
|
TRACE(ERR, "computed packet size is 0!");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
@@ -180,7 +179,7 @@ Stream::_SetupBuffers()
|
|||||||
delete fDescriptors;
|
delete fDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
fAreaSize = sampleSize * kSamplesBufferSize;
|
fAreaSize = sampleSize * kSamplesBufferSize * kSamplesBufferCount;
|
||||||
TRACE(INF, "estimate fAreaSize:%d\n", fAreaSize);
|
TRACE(INF, "estimate fAreaSize:%d\n", fAreaSize);
|
||||||
|
|
||||||
// round up to B_PAGE_SIZE and create area
|
// round up to B_PAGE_SIZE and create area
|
||||||
@@ -210,19 +209,19 @@ Stream::_SetupBuffers()
|
|||||||
TRACE(INF, "Created area id:%d at addr:%#010x size:%#010lx\n",
|
TRACE(INF, "Created area id:%d at addr:%#010x size:%#010lx\n",
|
||||||
fArea, fDescriptors, fAreaSize);
|
fArea, fDescriptors, fAreaSize);
|
||||||
|
|
||||||
fDescriptorsCount = fAreaSize / fPacketSize;
|
fDescriptorsCount = fAreaSize / packetSize;
|
||||||
// we need same size sub-buffers. round it
|
// we need same size sub-buffers. round it
|
||||||
fDescriptorsCount = ROUNDDOWN(fDescriptorsCount, kSamplesBufferCount);
|
fDescriptorsCount = ROUNDDOWN(fDescriptorsCount, kSamplesBufferCount);
|
||||||
fDescriptors = new usb_iso_packet_descriptor[fDescriptorsCount];
|
fDescriptors = new usb_iso_packet_descriptor[fDescriptorsCount];
|
||||||
TRACE(INF, "descriptorsCount:%d\n", fDescriptorsCount);
|
TRACE(INF, "descriptorsCount:%d\n", fDescriptorsCount);
|
||||||
|
|
||||||
// samples count
|
// samples count
|
||||||
fSamplesCount = fDescriptorsCount * fPacketSize / sampleSize;
|
fSamplesCount = fDescriptorsCount * packetSize / sampleSize;
|
||||||
TRACE(INF, "samplesCount:%d\n", fSamplesCount);
|
TRACE(INF, "samplesCount:%d\n", fSamplesCount);
|
||||||
|
|
||||||
// initialize descriptors array
|
// initialize descriptors array
|
||||||
for (size_t i = 0; i < fDescriptorsCount; i++) {
|
for (size_t i = 0; i < fDescriptorsCount; i++) {
|
||||||
fDescriptors[i].request_length = fPacketSize;
|
fDescriptors[i].request_length = packetSize;
|
||||||
fDescriptors[i].actual_length = 0;
|
fDescriptors[i].actual_length = 0;
|
||||||
fDescriptors[i].status = B_OK;
|
fDescriptors[i].status = B_OK;
|
||||||
}
|
}
|
||||||
@@ -317,7 +316,7 @@ Stream::_QueueNextTransfer(size_t queuedBuffer, bool start)
|
|||||||
Stream::_TransferCallback, this);
|
Stream::_TransferCallback, this);
|
||||||
|
|
||||||
TRACE(DTA, "frame:%#010x\n", fStartingFrame);
|
TRACE(DTA, "frame:%#010x\n", fStartingFrame);
|
||||||
return status; // B_OK;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -325,6 +324,8 @@ void
|
|||||||
Stream::_TransferCallback(void* cookie, status_t status, void* data,
|
Stream::_TransferCallback(void* cookie, status_t status, void* data,
|
||||||
size_t actualLength)
|
size_t actualLength)
|
||||||
{
|
{
|
||||||
|
TRACE(DTA, "st:%#010x, data:%#010x, len:%d\n", status, data, actualLength);
|
||||||
|
|
||||||
Stream* stream = (Stream*)cookie;
|
Stream* stream = (Stream*)cookie;
|
||||||
atomic_add(&stream->fInsideNotify, 1);
|
atomic_add(&stream->fInsideNotify, 1);
|
||||||
if (status == B_CANCELED || stream->fDevice->fRemoved || !stream->fIsRunning) {
|
if (status == B_CANCELED || stream->fDevice->fRemoved || !stream->fIsRunning) {
|
||||||
@@ -334,18 +335,15 @@ Stream::_TransferCallback(void* cookie, status_t status, void* data,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount;
|
|
||||||
|
|
||||||
stream->_DumpDescriptors();
|
stream->_DumpDescriptors();
|
||||||
|
|
||||||
/*status_t result =*/ stream->_QueueNextTransfer(stream->fCurrentBuffer, false);
|
|
||||||
|
|
||||||
if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount)
|
if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount)
|
||||||
TRACE(ERR, "Processed buffers overflow:%d\n", stream->fProcessedBuffers);
|
TRACE(ERR, "Processed buffers overflow:%d\n", stream->fProcessedBuffers);
|
||||||
|
|
||||||
release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
|
release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
|
||||||
|
|
||||||
TRACE(DTA, "st:%#010x, data:%#010x, len:%d\n", status, data, actualLength);
|
stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount;
|
||||||
|
status = stream->_QueueNextTransfer(stream->fCurrentBuffer, false);
|
||||||
|
|
||||||
atomic_add(&stream->fInsideNotify, -1);
|
atomic_add(&stream->fInsideNotify, -1);
|
||||||
}
|
}
|
||||||
@@ -498,13 +496,9 @@ Stream::GetBuffers(multi_buffer_list* List)
|
|||||||
uint32 stride = format->fSubframeSize * format->fNumChannels;
|
uint32 stride = format->fSubframeSize * format->fNumChannels;
|
||||||
descs[channel].stride = stride;
|
descs[channel].stride = stride;
|
||||||
|
|
||||||
// init to buffers area begin
|
size_t bufferSize = (fSamplesCount / kSamplesBufferCount) * stride;
|
||||||
descs[channel].base = (char*)fBuffers;
|
descs[channel].base = (char*)fBuffers;
|
||||||
// shift for whole buffer if required
|
|
||||||
size_t bufferSize = fPacketSize
|
|
||||||
* (fDescriptorsCount / kSamplesBufferCount);
|
|
||||||
descs[channel].base += buffer * bufferSize;
|
descs[channel].base += buffer * bufferSize;
|
||||||
// shift for channel if required
|
|
||||||
descs[channel].base += channel * format->fSubframeSize;
|
descs[channel].base += channel * format->fSubframeSize;
|
||||||
|
|
||||||
TRACE(DTA, "%d:%d: base:%#010x; stride:%#010x\n", buffer, channel,
|
TRACE(DTA, "%d:%d: base:%#010x; stride:%#010x\n", buffer, channel,
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ protected:
|
|||||||
size_t fCurrentBuffer;
|
size_t fCurrentBuffer;
|
||||||
size_t fSamplesCount;
|
size_t fSamplesCount;
|
||||||
|
|
||||||
size_t fPacketSize;
|
|
||||||
uint32 fStartingFrame;
|
uint32 fStartingFrame;
|
||||||
int32 fProcessedBuffers;
|
int32 fProcessedBuffers;
|
||||||
int32 fInsideNotify;
|
int32 fInsideNotify;
|
||||||
|
|||||||
Reference in New Issue
Block a user