summaryrefslogtreecommitdiff
path: root/audio/Acx/Samples/Common/KeywordDetector.h
blob: 2d5293b861a915441e152770711647a95e15f532 (plain)
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;

};