Alejandro Acuña
2024-10-25 bf65497ed7abf9c669eb3cc0ba219dfa4494b759
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
 
'******************************************************************************
'* ChirpGenerator                                                             *
'*                                                                            *
'* This class implements a custom control to generate a chirp signal          *
'* The user can modify the frequency,output power and decay in real time.     *
'*                                                                            *
'* We calculate the minimum samples of the tone that we need to generate a    *
'* continous signal with the given sampling and output frequency.             *
'* Then, each time the caller want to have a new fragment of the signal, we   *
'* repeat the calculated samples as many times as we need to fill the output  *
'* buffer.                                                                    *
'*                                                                            *
'* EQUITEL - C.V. February 2007                                         ALMDI *
'******************************************************************************
 
Imports System.ComponentModel
Imports System.Math
 
Public Class ChirpGenerator
    Private mInternalBuffer As Short()
    Private mBufSize As Integer
    Private mSamplingFrequency As Integer = 8000
    Private mFrequency As Integer = 1000
    Private mPower As Double = -0
    Private mSignalIsGenerated As Boolean = False
    Private mDecayTime As Integer
    Private mPeriodSamples As Integer = 160
 
 
 
 
#Region "Propiedades"
 
    <Category("Signal"), DefaultValue(GetType(Integer), "8000"), _
     Description("Sampling frequency of the desired signal")> _
    Public Property SamplingFrequency() As Integer
        Get
            Return mSamplingFrequency
        End Get
        Set(ByVal value As Integer)
            If value >= 8000 AndAlso value <= 96000 Then
                mSamplingFrequency = value
            End If
        End Set
    End Property
 
    <Category("Signal"), DefaultValue(GetType(Integer), "1000"), _
     Description("Frequency of the desired signal")> _
    Public Property Frequency() As Integer
        Get
            Return mFrequency
        End Get
        Set(ByVal value As Integer)
            If value >= 100 AndAlso value <= mSamplingFrequency / 2 Then
                mFrequency = value
                CtrlFrequency.Value = value
                lblFrequency.Text = Format(mFrequency / 1000, "0.0 kHz")
                CalculateSignal()
            End If
        End Set
    End Property
 
    <Category("Signal"), DefaultValue(GetType(Integer), "-100"), _
     Description("Relative output level of the signal in decibels")> _
    Public Property Power() As Double
        Get
            Return mPower
        End Get
        Set(ByVal value As Double)
            If value >= -100 AndAlso value <= 0 Then
                mPower = value
                CtrlPower.Value = value
                lblPower.Text = Format(value, "0 dB")
                CalculateSignal()
            End If
        End Set
    End Property
 
 
    <Category("Signal"), DefaultValue(GetType(Integer), "10"), _
     Description("Time the signal takes to fall to the 10% of amplitude (in ms)")> _
    Public Property T_Decay() As Double
        Get
            If mDecayTime < 1 Then mDecayTime = 1
            Return mDecayTime
        End Get
        Set(ByVal value As Double)
            If value <= 100 AndAlso value > 1 Then
                mDecayTime = value
                CtrlDecay.Value = value
                LblDecay.Text = Format(value, "000 ms")
                CalculateSignal()
            End If
        End Set
    End Property
 
 
 
 
    <Category("Signal"), DefaultValue(GetType(Integer), "20"), _
 Description("Period of the Chirp (in ms)")> _
    Public Property ChirpPeriod() As Integer
        Get
            Return (mPeriodSamples * 1000) / mSamplingFrequency
        End Get
        Set(ByVal value As Integer)
            If value <= 1000 AndAlso value > 1 Then
                mPeriodSamples = value * (mSamplingFrequency / 1000)
                LblPeriod.Text = Format(value, "000 ms")
                CalculateSignal()
            End If
        End Set
    End Property
 
 
#End Region
 
 
    Private Sub CalculateSignal()
        Dim i As Integer
        Dim t As Double
        Dim W As Double
        Dim Factor As Double
        Dim Vmax As Integer
 
 
        ReDim mInternalBuffer(mPeriodSamples - 1)
        mBufSize = mPeriodSamples
        W = 2 * 3.141592659 * mFrequency
        Factor = 20 ^ (mPower / (10 * 3))
        Vmax = Int(32767 * Factor)
        For i = 0 To mPeriodSamples - 1
            t = i * (1 / mSamplingFrequency)
            Try
                mInternalBuffer(i) = Vmax * Sin(W * t) * Exp(-t / (T_Decay / 2302))
            Catch e As Exception
                MsgBox("Chirp signal generation error", MsgBoxStyle.Critical)
            End Try
        Next
        mSignalIsGenerated = True
    End Sub
 
    Private Sub Power_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CtrlPower.Scroll
        Power = CtrlPower.Value
    End Sub
 
    Private Sub Frequency_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CtrlFrequency.Scroll
        CtrlFrequency.Value = Int(CtrlFrequency.Value / 100) * 100
        Frequency = CtrlFrequency.Value
    End Sub
 
    Private Sub CtrlDecay_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CtrlDecay.Scroll
        T_Decay = CtrlDecay.Value
    End Sub
 
    Private Sub CtrlPeriod_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CtrlPeriod.Scroll
        ChirpPeriod = CtrlPeriod.Value
    End Sub
 
    Public Sub OutputPacket(ByRef Buffer As Short(), ByVal NumSamples As Integer)
        Dim i As Integer
        Static mInternalBufferPointer As Integer = 0
 
        If Not mSignalIsGenerated Then CalculateSignal()
        For i = 0 To NumSamples - 1
            Buffer(i) = mInternalBuffer(mInternalBufferPointer)
            mInternalBufferPointer += 1
            If mInternalBufferPointer = mBufSize Then
                mInternalBufferPointer = 0
            End If
        Next
    End Sub
 
End Class