summaryrefslogtreecommitdiff
path: root/AVStream/avssamp/wave.cpp
diff options
context:
space:
mode:
authorWei Mao <[email protected]>2017-03-17 19:47:04 -0700
committerWei Mao <[email protected]>2017-03-17 19:47:04 -0700
commit1a3e0d580380e58bf336a242d2affc8a1e2d1ddf (patch)
treebf5d9c5b0b4cba1b81726b9f78c4d5ff5c636fea /AVStream/avssamp/wave.cpp
parentda21c8784c83c5fd614f3030323e229d6a5fb10e (diff)
Fix cases
Diffstat (limited to 'AVStream/avssamp/wave.cpp')
-rw-r--r--AVStream/avssamp/wave.cpp598
1 files changed, 598 insertions, 0 deletions
diff --git a/AVStream/avssamp/wave.cpp b/AVStream/avssamp/wave.cpp
new file mode 100644
index 00000000..7af2f60a
--- /dev/null
+++ b/AVStream/avssamp/wave.cpp
@@ -0,0 +1,598 @@
+/**************************************************************************
+
+ AVStream Filter-Centric Sample
+
+ Copyright (c) 1999 - 2001, Microsoft Corporation
+
+ File:
+
+ wave.cpp
+
+ Abstract:
+
+ Wave object implementation.
+
+ History:
+
+ Created 6/28/01
+
+**************************************************************************/
+
+#include "avssamp.h"
+
+/**************************************************************************
+
+ PAGED CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg("PAGE")
+#endif // ALLOC_PRAGMA
+
+
+CWaveObject::
+~CWaveObject (
+ )
+
+/*++
+
+Routine Description:
+
+ Destroy a wave object.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PAGED_CODE();
+
+ if (m_WaveData) {
+ ExFreePool (m_WaveData);
+ }
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CWaveObject::
+ParseForBlock (
+ IN HANDLE FileHandle,
+ IN ULONG BlockHeader,
+ IN OUT PLARGE_INTEGER BlockPosition,
+ OUT PULONG BlockSize
+ )
+
+/*++
+
+Routine Description:
+
+ Given that BlockPosition points to the offset of the start of a RIFF block,
+ continue parsing the specified file until a block with the header of
+ BlockHeader is found. Return the position of the block data and the size
+ of the block.
+
+Arguments:
+
+ FileHandle -
+ Handle to the file to parse
+
+ BlockHeader -
+ The block header to scan for
+
+ BlockPosition -
+ INPUT : Points to the block header to start at
+ OUTPUT: If successful, points to the block data for the sought block
+ If unsuccessful, unchanged
+
+ BlockSize -
+ On output, if successful -- the size of the sought block will be
+ placed here
+
+Return Value:
+
+ Success / Failure of the search
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ NTSTATUS Status;
+ ULONG FmtBlockSize = 0;
+ LARGE_INTEGER ReadPos = *BlockPosition;
+ IO_STATUS_BLOCK iosb;
+
+ while (1) {
+ ULONG BlockHeaderData [2];
+
+ Status = ZwReadFile (
+ FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &iosb,
+ BlockHeaderData,
+ sizeof (BlockHeaderData),
+ &ReadPos,
+ NULL
+ );
+
+ if (NT_SUCCESS (Status)) {
+ if (BlockHeaderData [0] == BlockHeader) {
+ FmtBlockSize = BlockHeaderData [1];
+ ReadPos.QuadPart += 0x8;
+ break;
+ } else {
+ //
+ // This isn't a format block. Just ignore it. All we
+ // care about is the format block and the PCM data.
+ //
+ ReadPos.QuadPart += BlockHeaderData [1] + 0x8;
+ }
+ } else {
+ break;
+ }
+
+ }
+
+ if (FmtBlockSize == 0) {
+ Status = STATUS_NOT_FOUND;
+ } else {
+ *BlockPosition = ReadPos;
+ *BlockSize = FmtBlockSize;
+ }
+
+ return Status;
+
+}
+
+/*************************************************/
+
+
+NTSTATUS
+CWaveObject::
+ParseAndRead (
+ )
+
+/*++
+
+Routine Description:
+
+ Parse the wave file and read the data into an internally allocated
+ buffer. This prepares to synthesize audio data from the wave
+ object.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+ If the wave is unrecognized, unparsable, or insufficient memory
+ exists to allocate the internal buffer, an error code will
+ be returned and the object will be incapable of synthesizing
+ audio data based on the wave.
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ IO_STATUS_BLOCK iosb;
+ UNICODE_STRING FileName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE FileHandle = NULL;
+ FILE_OBJECT *FileObj;
+
+ RtlInitUnicodeString (&FileName, m_FileName);
+
+ InitializeObjectAttributes (
+ &ObjectAttributes,
+ &FileName,
+ (OBJ_CASE_INSENSITIVE |
+ OBJ_KERNEL_HANDLE),
+ NULL,
+ NULL
+ );
+
+ Status = ZwCreateFile (
+ &FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &iosb,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ FILE_OPEN,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0
+ );
+
+ if (NT_SUCCESS (Status)) {
+ ULONG RiffWaveHeader [3];
+
+ //
+ // Read the header: RIFF size WAVE
+ //
+ Status = ZwReadFile (
+ FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &iosb,
+ RiffWaveHeader,
+ sizeof (RiffWaveHeader),
+ NULL,
+ NULL
+ );
+
+ //
+ // Ensure that this is a RIFF file and it's a WAVE.
+ //
+ if (NT_SUCCESS (Status)) {
+
+ if (RiffWaveHeader [0] != 'FFIR' ||
+ RiffWaveHeader [2] != 'EVAW') {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ //
+ // Find the wave format block and ensure it's WAVEFORMATEX and PCM
+ // data. Otherwise, this can't parse the wave.
+ //
+ LARGE_INTEGER ReadPos;
+ ReadPos.QuadPart = 0xc;
+ ULONG FmtBlockSize = 0;
+
+ if (NT_SUCCESS (Status)) {
+ Status = ParseForBlock (FileHandle, ' tmf', &ReadPos, &FmtBlockSize);
+ }
+
+ //
+ // If the format block was not found, the file cannot be parsed. If the
+ // format block is unrecognized, the file cannot be parsed.
+ //
+ if (FmtBlockSize >= sizeof (m_WaveFormat)) {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS (Status)) {
+ Status = ZwReadFile (
+ FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &iosb,
+ &m_WaveFormat,
+ FmtBlockSize,
+ &ReadPos,
+ NULL
+ );
+ }
+
+ if (NT_SUCCESS (Status)) {
+ if (m_WaveFormat.wFormatTag != WAVE_FORMAT_PCM) {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ ReadPos.QuadPart += FmtBlockSize;
+
+ //
+ // Find the data block and read it in.
+ //
+ ULONG DataBlockSize;
+ if (NT_SUCCESS (Status)) {
+ Status = ParseForBlock (FileHandle, 'atad', &ReadPos, &DataBlockSize);
+ }
+
+ //
+ // Perform a slight validation.
+ //
+ if (NT_SUCCESS (Status) &&
+ (DataBlockSize == 0 ||
+ (DataBlockSize & (m_WaveFormat.nBlockAlign - 1)))) {
+
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // If we're okay so far, allocate memory for the wave data.
+ //
+ if (NT_SUCCESS (Status)) {
+ m_WaveData = reinterpret_cast <PUCHAR> (
+ ExAllocatePoolWithTag (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG)
+ );
+
+ if (!m_WaveData) {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ //
+ // Read the wave data in.
+ //
+ if (NT_SUCCESS (Status)) {
+ Status = ZwReadFile (
+ FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &iosb,
+ m_WaveData,
+ DataBlockSize,
+ &ReadPos,
+ NULL
+ );
+
+ m_WaveSize = DataBlockSize;
+ }
+
+ //
+ // If we failed, clean up.
+ //
+ if (!NT_SUCCESS (Status)) {
+ if (m_WaveData) {
+ ExFreePool (m_WaveData);
+ m_WaveData = NULL;
+ }
+ }
+
+ if (FileHandle) {
+ ZwClose (FileHandle);
+ }
+
+ return Status;
+}
+
+/*************************************************/
+
+
+void
+CWaveObject::
+WriteRange (
+ OUT PKSDATARANGE_AUDIO DataRange
+ )
+
+/*++
+
+Routine Description:
+
+ Fill out the extended portion of the audio data range at DataRange. This
+ includes the channel, bps, and frequency fields.
+
+Arguments:
+
+ DataRange -
+ The data range to fill out
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PAGED_CODE();
+
+ DataRange -> MaximumChannels = m_WaveFormat.nChannels;
+ DataRange -> MinimumBitsPerSample =
+ DataRange -> MaximumBitsPerSample =
+ m_WaveFormat.wBitsPerSample;
+ DataRange -> MinimumSampleFrequency =
+ DataRange -> MaximumSampleFrequency =
+ m_WaveFormat.nSamplesPerSec;
+
+
+}
+
+/**************************************************************************
+
+ LOCKED CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg()
+#endif // ALLOC_PRAGMA
+
+
+void
+CWaveObject::
+SkipFixed (
+ IN LONGLONG TimeDelta
+ )
+
+/*++
+
+Routine Description:
+
+ Skip ahead a specific time delta within the wave.
+
+Arguments:
+
+ TimeDelta -
+ The amount of time to skip ahead.
+
+--*/
+
+{
+ if (TimeDelta > 0) {
+
+ //
+ // Compute the number of bytes of audio data necessary to move the
+ // stream forward TimeDelta time. Remember that TimeDelta is in
+ // units of 100nS.
+ //
+ ULONG Samples = (ULONG)(
+ (m_WaveFormat.nSamplesPerSec * TimeDelta) / 10000000
+ );
+
+ ULONG Bytes = Samples * (m_WaveFormat.wBitsPerSample / 8) *
+ m_WaveFormat.nChannels;
+
+ m_WavePointer = (m_WavePointer + Bytes) % m_WaveSize;
+
+ m_SynthesisTime += TimeDelta;
+
+ }
+
+}
+
+
+ULONG
+CWaveObject::
+SynthesizeFixed (
+ IN LONGLONG TimeDelta,
+ IN PVOID Buffer,
+ IN ULONG BufferSize
+ )
+
+/*++
+
+Routine Description:
+
+ Copy wave data from our wave block in order to synthesize forward in time
+ TimeDelta (in 100nS units).
+
+Arguments:
+
+ TimeDelta -
+ The amount of time to move the stream (in 100nS increments)
+
+ Buffer -
+ The buffer to synthesize into
+
+ BufferSize -
+ The size of the buffer
+
+Return Value:
+
+ Number of bytes synthesized.
+
+--*/
+
+{
+
+ //
+ // If there is no time delta, return 0.
+ //
+ if (TimeDelta < 0)
+ return 0;
+
+ //
+ // Compute the number of bytes of audio data necessary to move the stream
+ // forward TimeDelta time. Remember that TimeDelta is in units of 100nS.
+ //
+ ULONG Samples = (ULONG)(
+ (m_WaveFormat.nSamplesPerSec * TimeDelta) / 10000000
+ );
+
+ ULONG Bytes = Samples * (m_WaveFormat.wBitsPerSample / 8) *
+ m_WaveFormat.nChannels;
+
+ //
+ // Now that we have a specified number of bytes, we determine how many
+ // to really copy based on the Size of the buffer.
+ //
+ if (Bytes > BufferSize) Bytes = BufferSize;
+
+ //
+ // Because the buffer is looping, this may multiple distinct copies. For
+ // large wave files, this may be two chunks. For small wave files, this
+ // may be MANY distinct chunks.
+ //
+ ULONG BytesRemaining = Bytes;
+ PUCHAR DataCopy = reinterpret_cast <PUCHAR> (Buffer);
+
+ while (BytesRemaining) {
+ ULONG ChunkCount = m_WaveSize - m_WavePointer;
+ if (ChunkCount > BytesRemaining) ChunkCount = BytesRemaining;
+
+ RtlCopyMemory (
+ DataCopy,
+ m_WaveData + m_WavePointer,
+ ChunkCount
+ );
+
+ m_WavePointer += ChunkCount;
+ if (m_WavePointer >= m_WaveSize) m_WavePointer -= m_WaveSize;
+
+ BytesRemaining -= ChunkCount;
+ DataCopy += ChunkCount;
+
+ }
+
+ //
+ // Consider that we have synthesized up to the specified time. If the
+ // buffer was not large enough to do this, we'll end up falling behind
+ // the synthesis time. This does not skip samples.
+ //
+ m_SynthesisTime += TimeDelta;
+
+ return Bytes;
+
+}
+
+
+ULONG
+CWaveObject::
+SynthesizeTo (
+ IN LONGLONG StreamTime,
+ IN PVOID Buffer,
+ IN ULONG BufferSize
+ )
+
+/*++
+
+Routine Description:
+
+ Copy wave data from our wave block in order to synthesize the stream
+ up to the specified stream time. If the buffers are not large enough,
+ this will fall behind on synthesis.
+
+Arguments:
+
+ StreamTime -
+ The time to synthesize up to
+
+ Buffer -
+ The buffer to copy synthesized wave data into
+
+ BufferSize -
+ The size of the buffer
+
+Return Value:
+
+ The number of bytes used.
+
+--*/
+
+{
+
+ LONGLONG TimeDelta = StreamTime - m_SynthesisTime;
+
+ return SynthesizeFixed (TimeDelta, Buffer, BufferSize);
+
+
+}
+