📄 audioparsebuffer.cpp
字号:
}
DWORD buffer_size = _p_current_buffer->StreamHeader->FrameExtent;
//complete the buffer if it is full
_p_current_buffer->StreamHeader->DataUsed = buffer_size;
_p_pin->onBufferComplete();
_channel1_samples_in_buffer = 0;
_channel2_samples_in_buffer = 0;
_p_current_buffer = NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
AudioIISBuffer::AudioIISBuffer():
_p_pin(NULL),
_remain_in_buffer(0),
_p_current_buffer(NULL),
_fail_count(0),
_p_partial_buffer(NULL),
_bytes_in_partial_buffer(0)
{
KeInitializeMutex(&_mutex, 0);
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID AudioIISBuffer::setPin(BasePin* p_pin)
{
KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );
_p_pin = p_pin;
_remain_in_buffer= 0;
_p_current_buffer = NULL;
_p_partial_buffer = NULL;
_bytes_in_partial_buffer = 0;
KeReleaseMutex(&_mutex, FALSE);
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID AudioIISBuffer::releasePin()
{
KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );
_p_pin = NULL;
_remain_in_buffer= 0;
_p_current_buffer = NULL;
_p_partial_buffer = NULL;
_bytes_in_partial_buffer = 0;
KeReleaseMutex(&_mutex, FALSE);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// NOTE: The format of the audio data in the buffer is as follows:
//
// Mako supports up to 4 channels of audio output at a time. If a channel is
// present in the current audio buffer, then a bit will be set in the data_id2 byte.
// Each channel will have 8 bytes of data in the buffer, or 4 2-byte samples. The
// samples themselves are byte swapped, so we must byte swap each WORD, (not each DWORD).
// Of the channels that are present in the buffer, they will be in the order of
// Channel A, Channel B, Channel C, Channel D, with only channels that are present
// having data.
//
// We only use channels A and B, (referred to below as 1 and 2). If A and B are both present
// the data from A is at offset 0 and the data from B is at offset 8. If A alone is present,
// the data is at offset 0. If B alone is present, the data is at offset 0. Any other
// channels that may be present are ignored.
//
DWORD AudioIISBuffer::parseBuffer(PBYTE p_data, DWORD data_count)
{
KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );
DWORD copy_length = 0;
//If we don't have a pin, just return the number of bytes we would have used.
if(!_p_pin)
{
KeReleaseMutex(&_mutex, FALSE);
return 0;
}
//Get a buffer to copy the data into
if(!_p_current_buffer)
{
_p_current_buffer = _p_pin->getNextBuffer();
}
if(!_p_current_buffer)
{
sleep(40); /// wait for pin buffer, unit: ms
_fail_count++;
if(_fail_count == 10)
{
KeReleaseMutex(&_mutex, FALSE);
return 0xffffffff; //error
}
KeReleaseMutex(&_mutex, FALSE);
//No available buffer, nothing to do
return 0;
}
DWORD buffer_size = _p_current_buffer->StreamHeader->FrameExtent;
PBYTE p_out_buffer = (PBYTE)_p_current_buffer->StreamHeader->Data;
if(_remain_in_buffer != 0) //continue to complete the last copy
{
copy_length = _remain_in_buffer;
RtlCopyMemory(p_out_buffer, p_data, copy_length);
completeCurrentBuffer();
return copy_length;
}
// const DWORD MAX_CHANNEL_SAMPLES_IN_BUFFER = buffer_size / 4;
if (data_count < buffer_size )
{
_remain_in_buffer = buffer_size - data_count;
copy_length = data_count;
}
else
{
copy_length = buffer_size;
}
//////////////////////////////////////////////////////////
RtlCopyMemory(p_out_buffer, p_data, copy_length);
//////////////////////////////////////////////////////////
if(_remain_in_buffer == 0)
{
completeCurrentBuffer();
}
KeReleaseMutex(&_mutex, FALSE);
return copy_length;
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID AudioIISBuffer::completeCurrentBuffer()
{
if(!_p_current_buffer)
{
return;
}
DWORD buffer_size = _p_current_buffer->StreamHeader->FrameExtent;
//complete the buffer if it is full
_p_current_buffer->StreamHeader->DataUsed = buffer_size;
_p_pin->onBufferComplete();
_remain_in_buffer = 0;
_p_current_buffer = NULL;
_fail_count = 0;
}
VOID AudioIISBuffer::completeBuffers(PBYTE p_data, DWORD data_count)
{
if(!_p_pin || !data_count)
{
return;
}
PBYTE p_audio_buffer = p_data;
DWORD bytes_left = data_count;
//First try to complete a partial audio buffer if there is one left over
if(_p_partial_buffer)
{
PKSSTREAM_HEADER p_stream_header = _p_partial_buffer->StreamHeader;
DWORD bytes_left_in_buffer =
p_stream_header->FrameExtent - _bytes_in_partial_buffer;
///////////////////////////////////////////////////////////////
if(bytes_left < bytes_left_in_buffer)
{
RtlCopyMemory(
(PBYTE)p_stream_header->Data + _bytes_in_partial_buffer,
p_audio_buffer,
bytes_left);
_bytes_in_partial_buffer += bytes_left;
return; // continue to copy buffer to pin_buffer
}
else
{
RtlCopyMemory(
(PBYTE)p_stream_header->Data + _bytes_in_partial_buffer,
p_audio_buffer,
bytes_left_in_buffer);
}
bytes_left -= bytes_left_in_buffer;
p_audio_buffer += bytes_left_in_buffer;
p_stream_header->DataUsed = p_stream_header->FrameExtent;
_p_pin->onBufferComplete();
_p_partial_buffer = NULL;
}
//Now fill any other buffers that we have enough data for.
while(bytes_left)
{
PKSSTREAM_POINTER p_next_buffer = _p_pin->getNextBuffer();
if(!p_next_buffer)
{
break;
}
PKSSTREAM_HEADER p_stream_header = p_next_buffer->StreamHeader;
DWORD bytes_to_copy = p_stream_header->FrameExtent;
if(bytes_to_copy > bytes_left)
{
bytes_to_copy = bytes_left;
}
RtlCopyMemory(
(PBYTE)p_stream_header->Data,
p_audio_buffer,
bytes_to_copy);
if(bytes_to_copy == p_stream_header->FrameExtent)
{
p_stream_header->DataUsed = p_stream_header->FrameExtent;
_p_pin->onBufferComplete();
}
else
{
//If there wasn't enough data to fill the buffer,
// save it in the partial buffer
_p_partial_buffer = p_next_buffer;
_bytes_in_partial_buffer = bytes_to_copy;
break;
}
p_audio_buffer += bytes_to_copy;
bytes_left -= bytes_to_copy;
}
}
VOID AudioIISBuffer::sleep(LONG time)
{
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
LARGE_INTEGER wait_time;
wait_time.LowPart = -(time*10000);
wait_time.HighPart = -1;
KeDelayExecutionThread(
KernelMode,
FALSE,
&wait_time);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -