Author: nyadav
Date: Tue May 31 16:30:46 2011
New Revision: 52020
URL:
http://svn.reactos.org/svn/reactos?rev=52020&view=rev
Log:
[AUDSRV] Use Double Buffering to Improve latency
Added:
branches/nyadav-audio-branch/base/services/audsrv/stream.c (with props)
Modified:
branches/nyadav-audio-branch/base/services/audsrv/CMakeLists.txt
branches/nyadav-audio-branch/base/services/audsrv/audsrv.c
branches/nyadav-audio-branch/base/services/audsrv/audsrv.h
branches/nyadav-audio-branch/base/services/audsrv/rpc.c
branches/nyadav-audio-branch/dll/win32/audsrvapi/audsrvapi.c
branches/nyadav-audio-branch/dll/win32/audsrvapi/dllmain.c
branches/nyadav-audio-branch/include/reactos/idl/audsrvrpc.idl
branches/nyadav-audio-branch/include/reactos/libs/audsrv/audsrvapi.h
Modified: branches/nyadav-audio-branch/base/services/audsrv/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/servic…
==============================================================================
--- branches/nyadav-audio-branch/base/services/audsrv/CMakeLists.txt [iso-8859-1]
(original)
+++ branches/nyadav-audio-branch/base/services/audsrv/CMakeLists.txt [iso-8859-1] Tue May
31 16:30:46 2011
@@ -6,7 +6,8 @@
list(APPEND SOURCE
audsrv.c
audsrv.rc
- rpc.c)
+ rpc.c
+ stream.c)
add_executable(audsrv ${SOURCE})
Modified: branches/nyadav-audio-branch/base/services/audsrv/audsrv.c
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/servic…
==============================================================================
--- branches/nyadav-audio-branch/base/services/audsrv/audsrv.c [iso-8859-1] (original)
+++ branches/nyadav-audio-branch/base/services/audsrv/audsrv.c [iso-8859-1] Tue May 31
16:30:46 2011
@@ -153,27 +153,24 @@
-void fill(MixerEngine * mixer)
+void fill(MixerEngine * mixer,int buffer)
{
DWORD Length;
UINT i = 0;
- mixer->mastervolume = 1000;
- mixer->masterchannels=2;
- mixer->masterfreq=48000;
- mixer->masterbitspersample=16;
- mixer->masterchannelmask = KSAUDIO_SPEAKER_STEREO;
+Sleep(100);
Length = mixer->masterfreq * mixer->masterchannels * mixer->masterbitspersample
/ 8;
- mixer->masterbuf = (PSHORT)HeapAlloc(GetProcessHeap(), 0, Length);
+ mixer->masterbuf[buffer] = (PSHORT)HeapAlloc(GetProcessHeap(), 0, Length);
while (i < Length / 2)
{
- mixer->masterbuf[i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi / 48000);
+ mixer->masterbuf[buffer][i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi /
48000);
i++;
- mixer->masterbuf[i] = 0x7FFF * sin(0.5 * (i - 2) * 500 * _2pi / 48000);
+ mixer->masterbuf[buffer][i] = 0x7FFF * sin(0.5 * (i - 2) * 500 * _2pi /
48000);
i++;
}
-}
-
-void initdevice(MixerEngine * mixer)
+ mixer->bytes_to_play = Length;
+}
+
+void playbuffer(MixerEngine * mixer,int buffer)
{
SP_DEVICE_INTERFACE_DATA InterfaceData;
SP_DEVINFO_DATA DeviceData;
@@ -186,7 +183,8 @@
DWORD Length;
BOOL Result;
NTSTATUS Status;
-
+if(mixer->masterbuf[buffer])
+{
//
// Get a handle to KS Audio Interfaces
//
@@ -195,7 +193,7 @@
NULL,
DIGCF_DEVICEINTERFACE |DIGCF_PRESENT);
- printf("DeviceHandle %p\n", DeviceHandle);
+ //printf("DeviceHandle %p\n", DeviceHandle);
//
// Enumerate the first interface
@@ -208,7 +206,7 @@
1,
&InterfaceData);
- printf("SetupDiEnumDeviceInterfaces %u Error %ld\n", Result,
GetLastError());
+ //printf("SetupDiEnumDeviceInterfaces %u Error %ld\n", Result,
GetLastError());
//
// Get the interface details (namely the device path)
@@ -227,7 +225,7 @@
NULL,
&DeviceData);
- wprintf(L"SetupDiGetDeviceInterfaceDetail %u Path DetailData %s\n", Result,
(LPWSTR)&DetailData->DevicePath[0]);
+ //wprintf(L"SetupDiGetDeviceInterfaceDetail %u Path DetailData %s\n",
Result, (LPWSTR)&DetailData->DevicePath[0]);
//
// Open a handle to the device
@@ -240,7 +238,7 @@
FILE_ATTRIBUTE_NORMAL,
NULL);
- printf("Handle %p\n", mixer->FilterHandle);
+ //printf("Handle %p\n", mixer->FilterHandle);
//
// Close the interface handle and clean up
@@ -273,7 +271,7 @@
//
// Setup the KS Data Format Information
//
- printf("DataFormat %p %p\n", DataFormat,(PVOID)((((ULONG_PTR)DataFormat +
7)) & ~7));
+ //printf("DataFormat %p %p\n", DataFormat,(PVOID)((((ULONG_PTR)DataFormat +
7)) & ~7));
DataFormat->Flags = 0;
DataFormat->Reserved = 0;
@@ -294,14 +292,14 @@
WaveFormat->Samples.wValidBitsPerSample = mixer->masterbitspersample;
WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- printf("Creating pin\n");
+ //printf("Creating pin\n");
//
// Create the pin
//
Status = KsCreatePin(mixer->FilterHandle, PinConnect, GENERIC_READ|GENERIC_WRITE,
&(mixer->PinHandle));
- printf("PinHandle %p Status %lx\n", mixer->PinHandle, Status);
+ //printf("PinHandle %p Status %lx\n", mixer->PinHandle, Status);
Length = mixer->masterfreq * mixer->masterchannels *
mixer->masterbitspersample / 8;
@@ -311,9 +309,9 @@
mixer->Packet = (PKSSTREAM_HEADER)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(KSSTREAM_HEADER));
- mixer->Packet->Data = mixer->masterbuf;
- mixer->Packet->FrameExtent = Length;
- mixer->Packet->DataUsed = Length;
+ mixer->Packet->Data = mixer->masterbuf[buffer];
+ mixer->Packet->FrameExtent = mixer->bytes_to_play;
+ mixer->Packet->DataUsed = mixer->bytes_to_play;
mixer->Packet->Size = sizeof(KSSTREAM_HEADER);
mixer->Packet->PresentationTime.Numerator = 1;
mixer->Packet->PresentationTime.Denominator = 1;
@@ -338,13 +336,6 @@
sizeof(State),
&Length,
NULL);
-}
-void playbuffer(MixerEngine * mixer)
-{
- DWORD Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
- //
- // Play our 1-second buffer
- //
DeviceIoControl(mixer->PinHandle,
IOCTL_KS_WRITE_STREAM,
@@ -355,14 +346,6 @@
&Length,
NULL);
-}
-void closedevice(MixerEngine * mixer)
-{
- KSSTATE State;
- DWORD Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
- //
- // Change the state to stop
- //
State = KSSTATE_STOP;
DeviceIoControl(mixer->PinHandle,
IOCTL_KS_PROPERTY,
@@ -375,17 +358,21 @@
CloseHandle(mixer->PinHandle);
CloseHandle(mixer->FilterHandle);
-
+}
}
DWORD WINAPI RunMixerThread(LPVOID param)
{
MixerEngine * mixer = (MixerEngine *) param;
- SetEvent(mixer->EventPool[0]);
+
+ SetEvent(mixer->played);
while(1)
{
- while(WaitForSingleObject(mixer->EventPool[0],100)!=0){if(mixer->dead)goto DEAD;}
- fill(mixer);
- SetEvent(mixer->EventPool[1]);
+ while(WaitForSingleObject(mixer->streampresent,100)!=0){if(mixer->dead)goto DEAD;}
/*Check if there is at least one stream present.*/
+
+ while(WaitForSingleObject(mixer->played,100)!=0){if(mixer->dead)goto DEAD;}
+ fill(mixer,1-mixer->playcurrent);
+ SetEvent(mixer->filled);
+
}
DEAD:
printf("\nMixer Thread Ended\n");
@@ -396,11 +383,11 @@
MixerEngine * mixer = (MixerEngine *) param;
while(1)
{
- while(WaitForSingleObject(mixer->EventPool[1],100)!=0){if(mixer->dead)goto
DEAD;}
- initdevice(mixer);
- playbuffer(mixer);
- closedevice(mixer);
- SetEvent(mixer->EventPool[0]);
+ while(WaitForSingleObject(mixer->filled,100)!=0){if(mixer->dead)goto DEAD;}
+ SetEvent(mixer->played);
+ playbuffer(mixer,mixer->playcurrent);
+
+ mixer->playcurrent=1-mixer->playcurrent;
}
DEAD:
@@ -481,8 +468,12 @@
pengine->mute=FALSE;
pengine->dead=0;
- pengine->EventPool[0]=CreateEvent(NULL,FALSE,FALSE,NULL);
- pengine->EventPool[1]=CreateEvent(NULL,FALSE,FALSE,NULL);
+ pengine->playcurrent=1;
+ pengine->masterbuf[0] = NULL;
+ pengine->masterbuf[1] = NULL;
+ pengine->played=CreateEvent(NULL,FALSE,FALSE,NULL);
+ pengine->filled=CreateEvent(NULL,FALSE,FALSE,NULL);
+ pengine->streampresent=CreateEvent(NULL,TRUE,FALSE,NULL);
SetConsoleCtrlHandler(close,TRUE);
SpawnMixerThread(pengine);
SpawnPlayerThread(pengine);
@@ -510,8 +501,12 @@
pengine->mute=FALSE;
pengine->dead=0;
- pengine->EventPool[0]=CreateEvent(NULL,FALSE,FALSE,NULL);
- pengine->EventPool[1]=CreateEvent(NULL,FALSE,FALSE,NULL);
+ pengine->playcurrent=1;
+ pengine->masterbuf[0] = NULL;
+ pengine->masterbuf[1] = NULL;
+ pengine->played=CreateEvent(NULL,FALSE,FALSE,NULL);
+ pengine->filled=CreateEvent(NULL,FALSE,FALSE,NULL);
+ pengine->streampresent=CreateEvent(NULL,TRUE,FALSE,NULL);
SetConsoleCtrlHandler(close,TRUE);
SpawnMixerThread(pengine);
SpawnPlayerThread(pengine);
Modified: branches/nyadav-audio-branch/base/services/audsrv/audsrv.h
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/servic…
==============================================================================
--- branches/nyadav-audio-branch/base/services/audsrv/audsrv.h [iso-8859-1] (original)
+++ branches/nyadav-audio-branch/base/services/audsrv/audsrv.h [iso-8859-1] Tue May 31
16:30:46 2011
@@ -34,6 +34,8 @@
int bitspersample;
int channels;
ULONG channelmask;
+ HANDLE played;
+ HANDLE streamready;
HANDLE thread;
float balance;
struct ServerStream * next;
@@ -43,10 +45,13 @@
{
/*Should be Initialized at Server Start*/
char dead;
- HANDLE EventPool[2];//0=Played,1=Ready
+ HANDLE played;
+ HANDLE filled;
+ HANDLE streampresent;
HANDLE mixerthread;
HANDLE playerthread;
HANDLE rpcthread;
+ int playcurrent;
/*Should be Initialized at Server Start from configuration file,Currently there is no
configuration file so initialized to a fixed value at start*/
int mastervolume;
BOOL mute;
@@ -55,8 +60,9 @@
int masterchannels;
unsigned long masterchannelmask;
int masterbitspersample;
- PSHORT masterbuf;
+ PSHORT masterbuf[2];
/*Currently don't know the future of following variables*/
+ long bytes_to_play;
HANDLE FilterHandle;
HANDLE PinHandle;
PKSPROPERTY Property;
@@ -64,10 +70,15 @@
ServerStream * serverstreamlist;
} MixerEngine;
-extern MixerEngine engine;
+extern MixerEngine engine,*pengine;
/* rpc.c */
DWORD WINAPI RunRPCThread(LPVOID lpParameter);
+/* audsrv.c*/
+void fill(MixerEngine * mixer,int buffer);
+void playbuffer(MixerEngine * mixer,int buffer);
+/*stream.c*/
+HANDLE addstream(LONG frequency,int channels,int bitspersample, ULONG channelmask,int
volume,int mute,float balance);
/********************************/
#endif /* __AUDSRV_H__ */
Modified: branches/nyadav-audio-branch/base/services/audsrv/rpc.c
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/servic…
==============================================================================
--- branches/nyadav-audio-branch/base/services/audsrv/rpc.c [iso-8859-1] (original)
+++ branches/nyadav-audio-branch/base/services/audsrv/rpc.c [iso-8859-1] Tue May 31
16:30:46 2011
@@ -45,11 +45,13 @@
/*************************RPC Functions**********************************/
-NTSTATUS AUDInitStream( IN RPC_BINDING_HANDLE hBinding)
+int AUDInitStream( IN RPC_BINDING_HANDLE hBinding,LONG frequency,int channels,int
bitspersample, ULONG channelmask,int volume,int mute,float balance)
{
- UNIMPLEMENTED;/*Coolest Macro I have ever seen*/
- printf("Client Connected and called server's procedure\n");
- return STATUS_NOT_IMPLEMENTED;
+ HANDLE stream;
+ printf("Client Connected and Initiated Stream Freq: %ld,Channle: %d,Bitspersample:
%d,Mask: %ld,Volume: %d,Mute: %d,Balance:
%f\n",frequency,channels,bitspersample,channelmask,volume,mute,balance);
+ stream = addstream(frequency,channels,bitspersample,channelmask,volume,mute,balance);
+ if( stream == NULL ){return 0;}else{printf("Stream added\n");}
+ return (int)stream;
}
/*************************************************************************/
void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
Added: branches/nyadav-audio-branch/base/services/audsrv/stream.c
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/base/servic…
==============================================================================
--- branches/nyadav-audio-branch/base/services/audsrv/stream.c (added)
+++ branches/nyadav-audio-branch/base/services/audsrv/stream.c [iso-8859-1] Tue May 31
16:30:46 2011
@@ -1,0 +1,59 @@
+#include "audsrv.h"
+
+DWORD WINAPI RunStreamThread(LPVOID param)
+{
+ ServerStream * localstream = (ServerStream *) param;
+
+ SetEvent(localstream->streamready);
+ printf("Signaling Mixer Thread For First Stream\n");
+ SetEvent(pengine->streampresent);
+ while (1){OutputDebugStringA("Stream Thread Running.");Sleep(100);};
+ /*Clean Stream's data*/
+}
+
+HANDLE addstream(LONG frequency,int channels,int bitspersample, ULONG channelmask,int
volume,int mute,float balance)
+{
+ ServerStream * newstream,*localstream;
+ DWORD dwID;
+
+ /*Add Data to Linked list*/
+ localstream = pengine->serverstreamlist;
+ newstream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ServerStream));
+ if(newstream == NULL) {goto error;}
+ if(volume < 0) {newstream->volume = 0;}else if (volume > 1000)
{newstream->volume = 1000;}else {newstream->volume = volume;}
+ if(volume < -1.0) {newstream->volume = -1.0;}else if (volume > 1.0)
{newstream->volume = 1.0;}else {newstream->volume = volume;}
+ newstream->freq = frequency; /*TODO frequency validation required*/
+ newstream->bitspersample = bitspersample; /*TODO bitspersample validation*/
+ newstream->channels = channels; /*TODO validation*/
+ newstream->channelmask = channelmask; /*TODO validation*/
+
+ newstream->next = NULL;
+ newstream->played = CreateEvent(NULL,FALSE,FALSE,NULL);
+ newstream->streamready = CreateEvent(NULL,FALSE,FALSE,NULL);
+
+ if(newstream->played == NULL || newstream->streamready == NULL) {goto error;}
+ newstream->thread=CreateThread(NULL,0,RunStreamThread,newstream,0,&dwID);
+ if(newstream->thread == NULL) {goto error;}
+
+ WaitForSingleObject(newstream->streamready,INFINITE);
+
+ if(localstream == NULL)
+ {
+ pengine->serverstreamlist = localstream;
+
+ pengine->masterfreq=frequency;
+ pengine->masterchannels=channels;
+ pengine->masterchannelmask=channelmask;
+ pengine->masterbitspersample=bitspersample;
+ }
+ else
+ {
+ while(localstream->next != NULL){localstream = localstream->next;}
+ localstream->next = newstream;
+ }
+ return newstream->thread;
+
+error:
+ HeapFree(GetProcessHeap(), 0, newstream);
+ return NULL;
+}
Propchange: branches/nyadav-audio-branch/base/services/audsrv/stream.c
------------------------------------------------------------------------------
eol-style = native
Propchange: branches/nyadav-audio-branch/base/services/audsrv/stream.c
------------------------------------------------------------------------------
mime-type = text/plain
Propchange: branches/nyadav-audio-branch/base/services/audsrv/stream.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: branches/nyadav-audio-branch/base/services/audsrv/stream.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: branches/nyadav-audio-branch/dll/win32/audsrvapi/audsrvapi.c
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/dll/win32/a…
==============================================================================
--- branches/nyadav-audio-branch/dll/win32/audsrvapi/audsrvapi.c [iso-8859-1] (original)
+++ branches/nyadav-audio-branch/dll/win32/audsrvapi/audsrvapi.c [iso-8859-1] Tue May 31
16:30:46 2011
@@ -7,38 +7,25 @@
*/
WINAPI int initstream (ClientStream * clientstream,LONG frequency,int channels,int
bitspersample, ULONG channelmask,int volume,int mute,float balance)
{
- RPC_STATUS status;
- unsigned short * pszStringBinding = NULL;
-
-
- if(clientstream == NULL ) return -1;
+ int streamid;
+ if (clientstream == NULL ) return -1;
if (clientstream->callbacks.OpenComplete == NULL ||
clientstream->callbacks.BufferCopied == NULL || clientstream->callbacks.PlayComplete
== NULL) return -2;
/*Validity of all other data will be checked at server*/
/*Check Connection Status If not connected call Connect()*/
/*If connected Properly call the remote audsrv_initstream() function*/
- status =
RpcStringBindingComposeW(NULL,L"ncacn_np",NULL,L"\\pipe\\audsrv",
NULL,&pszStringBinding);
-
- status = RpcBindingFromStringBindingW(pszStringBinding, &audsrv_v0_0_c_ifspec);
-
- if (status) printf("Connection Problem p %d \n",status);
-
- status = RpcStringFree(&pszStringBinding);
-
- if (status) printf("Problem Freeing String : %d \n",status);
-
RpcTryExcept
{
- AUDInitStream (audsrv_v0_0_c_ifspec);
+ streamid = AUDInitStream
(audsrv_v0_0_c_ifspec,frequency,channels,bitspersample,channelmask,volume,mute,balance);
+ printf("AUDInitStream Returned %d",streamid);
}
- RpcExcept(1)
+ RpcExcept(1)
{
status = RpcExceptionCode();
printf("Runtime reported exception 0x%lx = %ld\n", status, status);
}
RpcEndExcept
- status = RpcBindingFree(&audsrv_v0_0_c_ifspec);
- if (status == RPC_S_INVALID_BINDING) printf("Error : %d Invalid RPC S
HANDLE\n",status);
+
/*Analyse the return by the function*/
/*Currently Suppose the return is 0 and a valid streamid is returned*/
clientstream->stream = &status;
Modified: branches/nyadav-audio-branch/dll/win32/audsrvapi/dllmain.c
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/dll/win32/a…
==============================================================================
--- branches/nyadav-audio-branch/dll/win32/audsrvapi/dllmain.c [iso-8859-1] (original)
+++ branches/nyadav-audio-branch/dll/win32/audsrvapi/dllmain.c [iso-8859-1] Tue May 31
16:30:46 2011
@@ -7,13 +7,27 @@
LPVOID lpReserved
)
{
-
+ RPC_STATUS status;
+ unsigned short * pszStringBinding = NULL;
+
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
+ status =
RpcStringBindingComposeW(NULL,L"ncacn_np",NULL,L"\\pipe\\audsrv",
NULL,&pszStringBinding);
+
+ status = RpcBindingFromStringBindingW(pszStringBinding, &audsrv_v0_0_c_ifspec);
+
+ if (status) printf("Connection Problem p %d \n",status);
+
+ status = RpcStringFree(&pszStringBinding);
+
+ if (status) printf("Problem Freeing String : %d \n",status);
+ break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
+ status = RpcBindingFree(audsrv_v0_0_c_ifspec);
+ if (status == RPC_S_INVALID_BINDING) printf("Error : %d Invalid RPC S
HANDLE\n",status);
break;
}
return TRUE;
Modified: branches/nyadav-audio-branch/include/reactos/idl/audsrvrpc.idl
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/include/rea…
==============================================================================
--- branches/nyadav-audio-branch/include/reactos/idl/audsrvrpc.idl [iso-8859-1]
(original)
+++ branches/nyadav-audio-branch/include/reactos/idl/audsrvrpc.idl [iso-8859-1] Tue May 31
16:30:46 2011
@@ -3,6 +3,7 @@
*/
#include <ms-dtyp.idl>
+
cpp_quote("#if !defined(__AUDSRV_H__) ")
typedef long NTSTATUS;
@@ -19,6 +20,7 @@
typedef AUDSRV_HANDLE *PAUDSRV_HANDLE;
typedef [handle, unique] LPWSTR AUDSRV_HANDLE_W;
typedef [handle, unique] LPSTR AUDSRV_HANDLE_A;
+
typedef struct _RPC_CLIENT_ID {
DWORD UniqueProcess;
@@ -37,6 +39,6 @@
interface audsrv
{
- NTSTATUS AUDInitStream([in] handle_t h1);
+ int AUDInitStream([in] handle_t h1,[in]LONG frequency,[in]int channels,[in]int
bitspersample,[in] ULONG channelmask,[in]int volume,[in]int mute,[in]float balance);
}
Modified: branches/nyadav-audio-branch/include/reactos/libs/audsrv/audsrvapi.h
URL:
http://svn.reactos.org/svn/reactos/branches/nyadav-audio-branch/include/rea…
==============================================================================
--- branches/nyadav-audio-branch/include/reactos/libs/audsrv/audsrvapi.h [iso-8859-1]
(original)
+++ branches/nyadav-audio-branch/include/reactos/libs/audsrv/audsrvapi.h [iso-8859-1] Tue
May 31 16:30:46 2011
@@ -7,6 +7,7 @@
#include <stdio.h>
/********************Structures*********************/
+
typedef struct CallBacks
{
void (*OpenComplete) (int error );
@@ -18,7 +19,7 @@
{
HANDLE stream;
int dead;
-HANDLE ClientEventPool[1]; /*[0]th event is for Activescheduler*/
+HANDLE ClientEventPool[1]; //0]th event is for Activescheduler
struct CallBacks callbacks;
} ClientStream;