Audiopositionseigenschaft

Der Client eines Audiotreibers verwendet die eigenschaft KSPROPERTY_AUDIO_POSITION , um die aktuelle Position in einem Audiostream abzurufen und festzulegen. Die -Eigenschaft verwendet eine KSAUDIO_POSITION-Struktur , um die aktuelle Position zu beschreiben. Die Struktur enthält zwei Elemente: PlayOffset und WriteOffset.

Die PlayOffset - und WriteOffset-Member definieren die Grenzen der Region des Clientpuffers, der derzeit für die ausschließliche Verwendung des Audiogeräts reserviert ist. Der Client muss davon ausgehen, dass das Gerät derzeit möglicherweise auf die in dieser Region enthaltenen Daten zugreift. Daher muss der Client nur auf die Teile des Puffers zugreifen, die sich außerhalb dieser Region befinden. Die Grenzen der Region verschieben sich, wenn der Stream voranschreitet.

Wenn der Clientpuffer in Schleifen ausgeführt wird (d. h. der Streamtyp ist KSINTERFACE_STANDARD_LOOPED_STREAMING), sind PlayOffset und WriteOffset pufferrelative Offsets. Das heißt, sie werden ab dem Start des Clientpuffers mit Schleifen als Byteoffsets angegeben. Wenn beide Offsetschritte bis zum Ende des Puffers inkrementieren, wird sie bis zum Anfang des Puffers umschließen. (Der Offset am Anfang des Puffers ist 0.) Daher überschreitet kein Offset jemals die Puffergröße.

Wenn der Clientpuffer nicht geloopt ist (d. h. der Streamtyp ist KSINTERFACE_STANDARD_STREAMING), sind PlayOffset und WriteOffset streamrelative Offsets. Das heißt, sie werden vom Anfang des Datenstroms als Byteoffsets angegeben. Diese Offsets können als Offsets in einen idealisierten Puffer betrachtet werden, der den gesamten Datenstrom enthält und von Anfang bis Ende zusammenhängend ist.

Bei einem Renderdatenstrom gibt das PlayOffset-Element die Wiedergabeposition des Datenstroms an, und das WriteOffset-Element gibt die Schreibposition des Datenstroms an. Die folgende Abbildung zeigt die Wiedergabe- und Schreibpositionen in einem Clientpuffer.

Diagramm, das die Wiedergabe- und Schreibpositionen in einem Renderdatenstrom veranschaulicht.

Die Wiedergabeposition ist der Byteoffset des Samples, das derzeit wiedergegeben wird (d. a. das Beispiel, das am Eingang des Digital-Analog-Konverters (DAC) verriegelt wird. Die Schreibposition ist die Position, über die der Client sicher in den Puffer schreiben kann. Während der Stream wiedergegeben wird, bewegen sich die Wiedergabe- und Schreibpositionen in der vorherigen Abbildung von links nach rechts. Die Schreibvorgänge des Clients müssen der Schreibposition voraus sein. Wenn der Puffer in einer Schleife ausgeführt wird, dürfen die Schreibvorgänge des Clients außerdem nie die Wiedergabeposition überholen.

Obwohl der WaveCyclic- oder WavePci-Porttreiber auf den Miniporttreiber angewiesen ist, um die Wiedergabeposition nachzuverfolgen, verfolgt der Porttreiber die Schreibposition. Die WaveCyclic- und WavePci-Porttreiber aktualisieren die Schreibposition wie folgt:

  • WaveCyclic

    Jedes Mal, wenn der WaveCyclic-Porttreiber IDmaChannel::CopyTo aufruft, um einen neuen Datenblock in den zyklischen Puffer (aus dem Clientpuffer) zu kopieren, wird die Schreibposition an den Speicherort (im Clientpuffer) des letzten Byte im Datenblock verschoben.

  • WavePci

    Standardmäßig wird jedes Mal, wenn der WavePci-Miniporttreiber IPortWavePciStream::GetMapping aufruft , um eine neue Zuordnung (eines Teils des Clientpuffers) abzurufen, und der Aufruf erfolgreich ist, die Schreibposition an den Speicherort (im Clientpuffer) des letzten Byte in der neuen Zuordnung weitergeleitet.

    Wenn der WavePci-Miniporttreiber das Standardverhalten überschreibt, indem er einen Prefetch-Offset für den Porttreiber angibt, ist die aktuelle Schreibposition immer gleich der Summe der aktuellen Wiedergabeposition und des Prefetch-Offsets. Weitere Informationen finden Sie unter Prefetch Offsets.

Im Fall eines Aufzeichnungsdatenstroms gibt das PlayOffset-Element die Datensatzposition des Datenstroms an, und das WriteOffset-Element gibt die Leseposition des Datenstroms an. Die folgende Abbildung zeigt die Datensatz- und Lesepositionen in einem Clientpuffer.

Diagramm zur Veranschaulichung von Datensatz- und Lesepositionen in einem Erfassungsstream.

Die Datensatzposition ist der Byteoffset des neuesten Beispiels, das am Ausgang des Analog-Digital-Konverters (ADC) verriegelt werden soll. (Diese Position gibt den Pufferspeicherort an, in den die DMA-Engine des Audiogeräts das Beispiel schließlich schreibt.) Die Leseposition ist die Position, über die der Client nicht sicher aus dem Puffer lesen kann. Wenn die Aufzeichnung des Datenstroms fortschreitet, werden die Lese- und Datensatzpositionen in der vorherigen Abbildung von links nach rechts vorgerückt. Die Lesevorgänge des Clients müssen die Leseposition nachstellen. Darüber hinaus müssen die Lesevorgänge des Clients, wenn der Puffer in einer Schleife ausgeführt wird, der Datensatzposition voraus bleiben.

Obwohl der WaveCyclic- oder WavePci-Porttreiber auf den Miniporttreiber angewiesen ist, um die Aufzeichnungsposition nachzuverfolgen, verfolgt der Porttreiber die Leseposition. Die WaveCyclic- und WavePci-Porttreiber aktualisieren die Leseposition wie folgt:

  • WaveCyclic

    Jedes Mal, wenn der WaveCyclic-Porttreiber IDmaChannel::CopyFrom aufruft, um einen neuen Datenblock aus dem zyklischen Puffer (in den Clientpuffer) zu kopieren, wird die Leseposition an den Speicherort (im Clientpuffer) des letzten Byte im Datenblock verschoben.

  • WavePci

    Jedes Mal, wenn der WavePci-Miniporttreiber IPortWavePciStream::ReleaseMapping aufruft , um eine zuvor erworbene Zuordnung (eines Teils des Clientpuffers) freizugeben, wird die Leseposition an den Speicherort (im Clientpuffer) des letzten Byte in der freigegebenen Zuordnung weitergeleitet.

Miniporttreiber müssen keine Handlerroutinen für KSPROPERTY_AUDIO_POSITION Eigenschaftenanforderungen implementieren. Stattdessen verarbeiten die WaveCyclic- und WavePci-Porttreiber diese Anforderungen im Auftrag von Miniporttreibern. Beim Verarbeiten einer Get-Eigenschaftsanforderung verfügt ein WaveCyclic- oder WavePci-Porttreiber bereits über alle Informationen, die er zum Berechnen des WriteOffset-Werts benötigt, aber er benötigt weiterhin Informationen vom Miniporttreiber, um den PlayOffset-Wert zu berechnen. Um diese Informationen abzurufen, ruft der Porttreiber die IMiniportWaveCyclicStream::GetPosition - oder IMiniportWavePciStream::GetPosition-Methode des Miniporttreibers auf.

Bei einem Renderstream ruft die GetPosition-Methode die Wiedergabeposition ab – den Byteoffset des Beispiels, das derzeit über die DAC wiedergegeben wird. Bei einem Erfassungsstream ruft die GetPosition-Methode die Datensatzposition ab – den Byteoffset des neuesten Beispiels, das vom ADC erfasst werden soll.

Beachten Sie, dass der von einem GetPosition-Aufruf abgerufene Offsetwert entweder eine Wiedergabeposition ist, die dem Signal entspricht, das derzeit über die Lautsprecherbuchse übertragen wird, oder eine Aufzeichnungsposition, die dem Signal entspricht, das derzeit über die Mikrofonbuchse empfangen wird. Es ist nicht die DMA-Position. (Die DMA-Position ist der Byteoffset des Beispiels, das die DMA-Engine im Audiogerät derzeit an oder aus dem DMA-Puffer überträgt.)

Einige Audiohardware enthält ein Positionsregister zum Nachverfolgen des Byteoffsets des Beispiels, das derzeit in jedem DAC oder ADC enthalten ist. In diesem Fall ruft die GetPosition-Methode einfach den Inhalt des Positionsregisters für den entsprechenden Stream ab. Andere Audiohardware kann den Treiber nur mit der DMA-Position versorgen. In diesem Fall muss die GetPosition-Methode eine optimale Schätzung des Byteoffsets des Beispiels im DAC oder ADC bereitstellen, indem die aktuelle DMA-Position und die internen Pufferverzögerungen des Geräts berücksichtigt werden.

Obwohl der Eigenschaftenhandler im WaveCyclic- oder WavePci-Porttreiber zwischen schleifenbasierten und nicht geloopten Puffern unterscheiden muss, um zu bestimmen, ob ein streamrelativer oder pufferrelativer Byteoffset bereitgestellt werden soll, ist dieses Detail (d. h. ob ein Puffer in Schleife oder nicht geloopt ist) für den Miniporttreiber transparent.

Die IMiniportWaveCyclicStream::GetPosition-Methode meldet immer eine pufferrelative Wiedergabe- oder Datensatzposition, unabhängig davon, ob der Clientpuffer in Schleife oder nicht geschleifet ist. Wenn der Clientpuffer in eine Schleife umgewandelt wird, konvertiert der Eigenschaftenhandler die vom Miniporttreiber gemeldete pufferrelative Position, die als Offset in den zyklischen Puffer ausgedrückt wird, in einen Offset in den Clientpuffer, den der Handler dann in das PlayOffset-Element schreibt. Wenn der Clientpuffer nicht geloopt ist, konvertiert der Eigenschaftenhandler die pufferrelative Wiedergabeposition in eine streamrelative Wiedergabeposition, bevor er sie in das PlayOffset-Element schreibt.

Die IMiniportWavePciStream::GetPosition-Methode meldet immer eine streamrelative Wiedergabe- oder Datensatzposition, unabhängig davon, ob der Clientpuffer in Schleife oder nicht geschleifet ist. Wenn der Clientpuffer in einer Schleife ausgeführt wird, konvertiert der Eigenschaftenhandler die streamrelative Wiedergabeposition in eine pufferrelative Wiedergabeposition (ausgedrückt als Offset in den Clientpuffer), bevor er sie in das PlayOffset-Element in der KSAUDIO_POSITION-Struktur in der Eigenschaftenanforderung schreibt. Wenn der Clientpuffer nicht geloopt ist, schreibt der Eigenschaftenhandler die streamrelative Position in das PlayOffset-Element .

Die Wiedergabe- oder Datensatzposition ist unmittelbar nach der Initialisierung des Streams 0. Durch einen Übergang zum KSSTATE_STOP Zustand (siehe KSSTATE) wird die Position auf 0 zurückgesetzt. Wenn der Stream durch einen Übergang von KSSTATE_RUN zu KSSTATE_PAUSE oder KSSTATE_ACQUIRE angehalten wird, friert die Position ein. Er wird beim Übergang von KSSTATE_PAUSE oder KSSTATE_ACQUIRE zurück zu KSSTATE_RUN wieder freigestellt.

Beispielimplementierungen von GetPosition-Methoden für WaveCyclic- und WavePci-Miniporttreiber finden Sie in den Beispiel-Audiotreibern im Windows Driver Kit (WDK).