1
+ '#If Win32 Then
2
+ 'Imports SlimDX.DirectSound
3
+ 'Imports SlimDX.Multimedia
4
+ 'Imports System.Runtime.InteropServices
5
+ 'Imports System.Threading
6
+
7
+ 'Public Class SpeakerAdpater
8
+ ' Inherits Adapter
9
+
10
+ ' <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)>
11
+ ' Private Shared Function GetDesktopWindow() As IntPtr
12
+ ' End Function
13
+
14
+ ' Private Enum WaveForms
15
+ ' Squared
16
+ ' Sinusoidal
17
+ ' End Enum
18
+
19
+ ' Private waveForm As WaveForms = WaveForms.Squared
20
+
21
+ ' Private Const ToRad As Double = Math.PI / 180
22
+
23
+ ' Private audioDev As DirectSound
24
+ ' Private bufPlayDesc As SoundBufferDescription
25
+ ' Private playBuf As SecondarySoundBuffer
26
+ ' Private notifySize As Integer
27
+ ' Private numberPlaybackNotifications As Integer = 8 ' 4
28
+ ' Private nextPlaybackOffset As Integer
29
+
30
+ ' Private mAudioBuffer() As Byte
31
+ ' Private audioWriteBufferPosition As Integer
32
+ ' Private Const sampleRate As Integer = 44100
33
+
34
+ ' Private mCPU As x8086
35
+ ' Private mEnabled As Boolean
36
+ ' Private playbackThread As Thread
37
+ ' Private cancelAllThreads As Boolean
38
+
39
+ ' Private mFrequency As Double
40
+ ' Private waveLength As Integer
41
+ ' Private halfWaveLength As Integer
42
+ ' Private bufferWritePosition As Integer
43
+ ' Private bufferReadPosition As Integer
44
+ ' Private currentStep As Integer
45
+
46
+ ' Private mVolume As Double
47
+
48
+ ' Public Sub New(cpu As x8086)
49
+ ' mCPU = cpu
50
+ ' If mCPU.PIT IsNot Nothing Then mCPU.PIT.Speaker = Me
51
+ ' mVolume = 0.05
52
+ ' End Sub
53
+
54
+ ' Public Property Frequency As Double
55
+ ' Get
56
+ ' Return mFrequency
57
+ ' End Get
58
+ ' Set(value As Double)
59
+ ' mFrequency = value
60
+ ' UpdateWaveformParameters()
61
+ ' End Set
62
+ ' End Property
63
+
64
+ ' Public Property Enabled As Boolean
65
+ ' Get
66
+ ' Return mEnabled
67
+ ' End Get
68
+ ' Set(value As Boolean)
69
+ ' mEnabled = value
70
+ ' UpdateWaveformParameters()
71
+ ' End Set
72
+ ' End Property
73
+
74
+ ' Public Property Volume As Double
75
+ ' Get
76
+ ' Return mVolume
77
+ ' End Get
78
+ ' Set(value As Double)
79
+ ' mVolume = value
80
+ ' End Set
81
+ ' End Property
82
+
83
+ ' Public ReadOnly Property AudioBuffer As Byte()
84
+ ' Get
85
+ ' Return mAudioBuffer
86
+ ' End Get
87
+ ' End Property
88
+
89
+ ' Private Sub UpdateWaveformParameters()
90
+ ' If mFrequency > 0 Then
91
+ ' waveLength = sampleRate / mFrequency
92
+ ' Else
93
+ ' waveLength = 0
94
+ ' End If
95
+
96
+ ' halfWaveLength = waveLength / 2
97
+ ' End Sub
98
+
99
+ ' Private Sub FillAudioBuffer()
100
+ ' Dim v As Double
101
+ ' Do
102
+ ' Select Case waveForm
103
+ ' Case WaveForms.Squared
104
+ ' If mEnabled Then
105
+ ' If currentStep <= halfWaveLength Then
106
+ ' v = -128
107
+ ' Else
108
+ ' v = 127
109
+ ' End If
110
+ ' Else
111
+ ' v = 0
112
+ ' End If
113
+ ' Case WaveForms.Sinusoidal
114
+ ' If mEnabled AndAlso waveLength > 0 Then
115
+ ' v = Math.Floor(Math.Sin((currentStep / waveLength) * (mFrequency / 2) * ToRad) * 128)
116
+ ' Else
117
+ ' v = 0
118
+ ' End If
119
+ ' End Select
120
+
121
+ ' v *= mVolume
122
+ ' If v <= 0 Then
123
+ ' v = 128 + v
124
+ ' Else
125
+ ' v += 127
126
+ ' End If
127
+ ' mAudioBuffer(bufferWritePosition) = v
128
+
129
+ ' currentStep += 1
130
+ ' If currentStep >= waveLength Then currentStep = 0
131
+
132
+ ' bufferWritePosition += 1
133
+ ' bufferWritePosition = bufferWritePosition Mod mAudioBuffer.Length
134
+ ' Loop Until cancelAllThreads OrElse bufferWritePosition = 0
135
+ ' End Sub
136
+
137
+ ' Private Sub MainLoop()
138
+ ' Do
139
+ ' waiter.WaitOne()
140
+
141
+ ' FillAudioBuffer()
142
+ ' Write()
143
+ ' Loop Until cancelAllThreads
144
+ ' End Sub
145
+
146
+ ' Public Overrides Sub CloseAdapter()
147
+ ' cancelAllThreads = True
148
+
149
+ ' Do
150
+ ' Thread.Sleep(10)
151
+ ' Loop While playbackThread.ThreadState <> ThreadState.Stopped
152
+
153
+ ' playBuf.Stop()
154
+ ' waiter.Set()
155
+
156
+ ' playBuf.Dispose()
157
+ ' audioDev.Dispose()
158
+ ' End Sub
159
+
160
+ ' Public Overrides ReadOnly Property Description As String
161
+ ' Get
162
+ ' Return "PC Speaker"
163
+ ' End Get
164
+ ' End Property
165
+
166
+ ' Public Overrides Function [In](port As Integer) As Integer
167
+ ' Return &HFF
168
+ ' End Function
169
+
170
+ ' Public Overrides Sub InitiAdapter()
171
+ ' ReDim mAudioBuffer(sampleRate / 100 - 1)
172
+
173
+ ' ' Define the capture format
174
+ ' Dim format As WaveFormat = New WaveFormat()
175
+ ' With format
176
+ ' .BitsPerSample = 8
177
+ ' .Channels = 1
178
+ ' .FormatTag = WaveFormatTag.Pcm
179
+ ' .SamplesPerSecond = sampleRate
180
+ ' .BlockAlignment = CShort(.Channels * .BitsPerSample / 8)
181
+ ' .AverageBytesPerSecond = .SamplesPerSecond * .BlockAlignment
182
+ ' End With
183
+
184
+ ' ' Define the size of the notification chunks
185
+ ' notifySize = mAudioBuffer.Length
186
+ ' notifySize -= notifySize Mod format.BlockAlignment
187
+
188
+ ' ' Create a buffer description object
189
+ ' bufPlayDesc = New SoundBufferDescription()
190
+ ' With bufPlayDesc
191
+ ' .Format = format
192
+ ' .Flags = BufferFlags.ControlPositionNotify Or
193
+ ' BufferFlags.GetCurrentPosition2 Or
194
+ ' BufferFlags.GlobalFocus Or
195
+ ' BufferFlags.Static Or
196
+ ' BufferFlags.ControlVolume Or
197
+ ' BufferFlags.ControlPan Or
198
+ ' BufferFlags.ControlFrequency
199
+ ' .SizeInBytes = notifySize * numberPlaybackNotifications
200
+ ' End With
201
+
202
+ ' audioDev = New DirectSound()
203
+ ' Dim windowHandle As IntPtr = GetDesktopWindow()
204
+ ' audioDev.SetCooperativeLevel(windowHandle, CooperativeLevel.Priority)
205
+ ' playBuf = New SecondarySoundBuffer(audioDev, bufPlayDesc)
206
+
207
+ ' ' Define the notification events
208
+ ' Dim np(numberPlaybackNotifications - 1) As NotificationPosition
209
+
210
+ ' For i As Integer = 0 To numberPlaybackNotifications - 1
211
+ ' np(i) = New NotificationPosition()
212
+ ' np(i).Offset = (notifySize * i) + notifySize - 1
213
+ ' np(i).Event = waiter
214
+ ' Next
215
+ ' playBuf.SetNotificationPositions(np)
216
+
217
+ ' nextPlaybackOffset = 0
218
+ ' playBuf.Play(0, PlayFlags.Looping)
219
+
220
+ ' playbackThread = New Thread(AddressOf MainLoop)
221
+ ' playbackThread.Start()
222
+ ' End Sub
223
+
224
+ ' Public Sub Write()
225
+ ' Dim lockSize As Integer
226
+
227
+ ' lockSize = playBuf.CurrentWritePosition - nextPlaybackOffset
228
+ ' If lockSize < 0 Then lockSize += bufPlayDesc.SizeInBytes
229
+
230
+ ' ' Block align lock size so that we always read on a boundary
231
+ ' lockSize -= lockSize Mod notifySize
232
+ ' If lockSize = 0 Then Exit Sub
233
+
234
+ ' playBuf.Write(Of Byte)(mAudioBuffer, nextPlaybackOffset, LockFlags.None)
235
+
236
+ ' nextPlaybackOffset += mAudioBuffer.Length
237
+ ' nextPlaybackOffset = nextPlaybackOffset Mod bufPlayDesc.SizeInBytes ' Circular buffer
238
+ ' End Sub
239
+
240
+ ' Public Overrides ReadOnly Property Name As String
241
+ ' Get
242
+ ' Return "Speaker"
243
+ ' End Get
244
+ ' End Property
245
+
246
+ ' Public Overrides Sub Out(port As Integer, value As Integer)
247
+
248
+ ' End Sub
249
+
250
+ ' Public Overrides Sub Run()
251
+ ' x8086.Notify("Speaker Running", x8086.NotificationReasons.Info)
252
+ ' End Sub
253
+
254
+ ' Public Overrides ReadOnly Property Type As Adapter.AdapterType
255
+ ' Get
256
+ ' Return AdapterType.Speaker
257
+ ' End Get
258
+ ' End Property
259
+
260
+ ' Public Overrides ReadOnly Property Vendor As String
261
+ ' Get
262
+ ' Return "xFX JumpStart"
263
+ ' End Get
264
+ ' End Property
265
+
266
+ ' Public Overrides ReadOnly Property VersionMajor As Integer
267
+ ' Get
268
+ ' Return 0
269
+ ' End Get
270
+ ' End Property
271
+
272
+ ' Public Overrides ReadOnly Property VersionMinor As Integer
273
+ ' Get
274
+ ' Return 0
275
+ ' End Get
276
+ ' End Property
277
+
278
+ ' Public Overrides ReadOnly Property VersionRevision As Integer
279
+ ' Get
280
+ ' Return 23
281
+ ' End Get
282
+ ' End Property
283
+ 'End Class
284
+ '#Else
285
+ 'Public Class SpeakerAdpater
286
+ ' Inherits Adapter
287
+
288
+ ' Public Sub New(cpu As x8086)
289
+
290
+ ' End Sub
291
+
292
+ ' Public Overrides Sub CloseAdapter()
293
+
294
+ ' End Sub
295
+
296
+ ' Public Overrides ReadOnly Property Description As String
297
+ ' Get
298
+ ' Return "Null PC Speaker"
299
+ ' End Get
300
+ ' End Property
301
+
302
+ ' Public Overloads Overrides Function [In](port As Integer) As Integer
303
+ ' Return 0
304
+ ' End Function
305
+
306
+ ' Public Overloads Overrides Sub Out(port As Integer, value As Integer)
307
+
308
+ ' End Sub
309
+
310
+ ' Public Overrides Sub InitiAdapter()
311
+
312
+ ' End Sub
313
+
314
+ ' Public Overrides ReadOnly Property Name As String
315
+ ' Get
316
+ ' Return "Null Speaker"
317
+ ' End Get
318
+ ' End Property
319
+
320
+ ' Public Overrides Sub Run()
321
+
322
+ ' End Sub
323
+
324
+ ' Public Overrides ReadOnly Property Type As Adapter.AdapterType
325
+ ' Get
326
+ ' Return AdapterType.Speaker
327
+ ' End Get
328
+ ' End Property
329
+
330
+ ' Public Overrides ReadOnly Property Vendor As String
331
+ ' Get
332
+ ' Return "xFX JumpStart"
333
+ ' End Get
334
+ ' End Property
335
+
336
+ ' Public Overrides ReadOnly Property VersionMajor As Integer
337
+ ' Get
338
+ ' Return 0
339
+ ' End Get
340
+ ' End Property
341
+
342
+ ' Public Overrides ReadOnly Property VersionMinor As Integer
343
+ ' Get
344
+ ' Return 0
345
+ ' End Get
346
+ ' End Property
347
+
348
+ ' Public Overrides ReadOnly Property VersionRevision As Integer
349
+ ' Get
350
+ ' Return 1
351
+ ' End Get
352
+ ' End Property
353
+ 'End Class
354
+ '#End If
0 commit comments