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