1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
/*++
Copyright (c) Microsoft Corporation All Rights Reserved
Module Name:
KeywordDetector.h
Abstract:
Sample Keyword Detector.
--*/
#pragma once
typedef struct
{
SOUNDDETECTOR_PATTERNHEADER Header;
LONGLONG ContosoDetectorConfigurationData;
} CONTOSO_KEYWORDCONFIGURATION;
typedef struct
{
SOUNDDETECTOR_PATTERNHEADER Header;
LONGLONG ContosoDetectorResultData;
ULONGLONG KeywordStartTimestamp;
ULONGLONG KeywordStopTimestamp;
GUID EventId;
} CONTOSO_KEYWORDDETECTIONRESULT;
DEFINE_GUID(CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2,
0x207f3d0c, 0x5c79, 0x496f, 0xa9, 0x4c, 0xd3, 0xd2, 0x93, 0x4d, 0xbf, 0xa9);
// {A537F559-2D67-463B-B10E-BEB750A21F31}
DEFINE_GUID(CONTOSO_KEYWORD1,
0xa537f559, 0x2d67, 0x463b, 0xb1, 0xe, 0xbe, 0xb7, 0x50, 0xa2, 0x1f, 0x31);
// {655E417A-80A5-4A77-B3F1-512EAF67ABCF}
DEFINE_GUID(CONTOSO_KEYWORD2,
0x655e417a, 0x80a5, 0x4a77, 0xb3, 0xf1, 0x51, 0x2e, 0xaf, 0x67, 0xab, 0xcf);
#define KEYWORDDETECTOR_POOLTAG 'KWS0'
class CKeywordDetector
{
public:
PAGED_CODE_SEG
CKeywordDetector();
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
NTSTATUS ResetDetector(_In_ GUID eventId);
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
NTSTATUS DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data);
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
NTSTATUS GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data);
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
ULONGLONG GetStartTimestamp();
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
ULONGLONG GetStopTimestamp();
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
NTSTATUS SetArmed(_In_ GUID eventId, _In_ BOOLEAN Arm);
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
VOID NotifyDetection();
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
NTSTATUS GetArmed(_In_ GUID eventId, _Out_ BOOLEAN *Arm);
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
VOID Run();
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
VOID Stop();
_IRQL_requires_min_(DISPATCH_LEVEL)
VOID DpcRoutine(_In_ LONGLONG PerformanceCounter, _In_ LONGLONG PerformanceFrequency);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS GetReadPacket(_In_ ULONG PacketCount, _In_ ULONG PacketSize, _Out_writes_(PacketSize) PVOID *Packets, _Out_ ULONG *PacketNumber, _Out_ ULONGLONG *PerformanceCount, _Out_ BOOLEAN *MoreData);
private:
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
VOID ResetFifo();
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
NTSTATUS ReadKeywordTimestampRegistry();
_IRQL_requires_max_(PASSIVE_LEVEL)
PAGED_CODE_SEG
VOID StartBufferingStream();
// The Contoso keyword detector processes 10ms packets of 16KHz 16-bit PCM
// audio samples
static const int SamplesPerSecond = 16000;
static const int SamplesPerPacket = (10 * SamplesPerSecond / 1000);
typedef struct
{
LIST_ENTRY ListEntry;
LONGLONG PacketNumber;
LONGLONG QpcWhenSampled;
UINT16 Samples[SamplesPerPacket];
} PACKET_ENTRY;
BOOLEAN m_streamRunning;
BOOLEAN m_SoundDetectorArmed1;
BOOLEAN m_SoundDetectorArmed2;
LONGLONG m_SoundDetectorData1;
LONGLONG m_SoundDetectorData2;
LONGLONG m_qpcStartCapture;
LONGLONG m_qpcFrequency;
LONGLONG m_nLastQueuedPacket;
ULONGLONG m_ullKeywordStartTimestamp;
ULONGLONG m_ullKeywordStopTimestamp;
KSPIN_LOCK PacketPoolSpinLock;
LIST_ENTRY PacketPoolHead;
PACKET_ENTRY PacketPool[1 * SamplesPerSecond / SamplesPerPacket]; // Enough storage for 1 second of audio data
KSPIN_LOCK PacketFifoSpinLock;
LIST_ENTRY PacketFifoHead;
};
|