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.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
Option Explicit 'Это ясно :)
'Установка типа переменных
Public hWaveIn& 'Контейнер уровня входа
Private bBufferFull As Boolean 'Контейнер статуса буфера (памяти); Лож/Истина
Private WaveData( 255 ) As Byte 'Звуковые данные
Type WAVEFORMATEX 'Формат и информация звуковых данных
wFormatTag As Integer 'Тег типа формата (звука)
nChannels As Integer 'Количество каналов
nSamplesPerSec As Long 'Кадров в секунду (кадр/сек)
nAvgBytesPerSec As Long 'Переростшые байты за сек.
nBlockAlign As Integer 'Блокировать направление
wBitsPerSample As Integer 'Бит/кадр
cbSize As Integer 'Размер даты
End Type
Type WAVEHDR 'Контейнер полученного звука (файла/битов)
lpData As Long 'Данные (контейнер)
dwBufferLength As Long 'Длина буфера (памяти)
dwBytesRecorded As Long 'Байтов записано
dwUser As Long 'Блок пользовательской памяти
dwFlags As Long 'Ниже описанные флашки (типы)
dwLoops As Long 'Повтор
lpNext As Long 'Следующий бит
Reserved As Long 'Обратное выделение
End Type
Type WAVEINCAPS 'Данные в колпачке
wMid As Integer 'Середина
wPid As Integer 'Пики (Peak)
vDriverVersion As Long 'Версия драйвера (системного)
szPname As String * 32 'Имя порта (Канала/Драйвера)
dwFormats As Long 'Нижеописанные форматы
wChannels As Integer 'Количество каналов
End Type
'Все библиотеки использованные в проекте
'Подробно ищите в интернете, не охота описовать или доке по API
Declare Function waveInAddBuffer Lib "winmm.dll" (ByVal hWaveIn As Long, lpWaveInHdr As WAVEHDR, ByVal uSize As Long) As Long
'Получиене количества звуковых устройств ( 0 при отсутсвии)
Declare Function waveInGetNumDevs Lib "winmm.dll" () As Long
'Открыть звуковой вход
Declare Function waveInOpen Lib "winmm.dll" (lphWaveIn As Long, ByVal uDeviceID As Long, lpFormat As WAVEFORMATEX, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
'Получить заголовок (канала)
Declare Function waveInPrepareHeader Lib "winmm.dll" (ByVal hWaveIn As Long, lpWaveInHdr As WAVEHDR, ByVal uSize As Long) As Long
'Сброс данных входа
Declare Function waveInReset Lib "winmm.dll" (ByVal hWaveIn As Long) As Long
'Открыти приёмного канала
Declare Function waveInStart Lib "winmm.dll" (ByVal hWaveIn As Long) As Long
'Отсановка приёма байтов входного канала
Declare Function waveInStop Lib "winmm.dll" (ByVal hWaveIn As Long) As Long
'Закрытие звукогого канала
Declare Function waveInClose Lib "winmm.dll" (ByVal hWaveIn As Long) As Long
'Негтовые (необработанные) заголовки
Declare Function waveInUnprepareHeader Lib "winmm.dll" (ByVal hWaveIn As Long, lpWaveInHdr As WAVEHDR, ByVal uSize As Long) As Long
'Установкаместоположения окна
Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Public Const CALLBACK_FUNCTION = &H30000 'Функция возврата
Public Const MM_WIM_DATA = &H3C0 'Контейнер переобразование данных
Public Const WAVE_FORMAT_PCM = 1 'Формат данных (1 по умолч.)
Public Const WAVE_MAPPER = -1& 'Wave Mapper системное устройство наблюдения за звуком
'Форматы (звуковых) данных
Public Const WAVE_FORMAT_1M08 = &H1 ' 11025 Гц, 8 Бит, Моно.
Public Const WAVE_FORMAT_2M08 = &H10 ' 22050 Гц, 8 Бит, Моно.
Public Const WAVE_FORMAT_4M08 = &H100 ' 44100 Гц, 8 Бит, Моноo.
'Расположение окна
Global Const HWND_TOP = 0 'Константа окно на пункт верх
Global Const HWND_TOPMOST = - 1 'Поверх всех окон
Global Const HWND_NOTOPMOST = -2 'Не повер всех окон (возврат в старое место)
Global Const SWP_NOMOVE = 2 'Не перетаскивать
Global Const SWP_NOSIZE = 1 'Не изменять размер
Global Const FLAGS = SWP_NOMOVE Or SWP_NOSIZE 'Флаги
Private Sub Main()
'Отсюда всё и начинается
#If Win32 Then 'Если система 32-разрядная то
If PrevInst Then End 'Если другая копия загружена не загружать эту
If Not WaveInPresent Then End 'Если нет звукого устройства ввода, завершит программу
frmMain.Show 'Отображать главное окно
#Else 'В противном случае (Если Винда не 32 а 16)
End 'Выйти с программы ничего не сделав
#End If
End Sub
Private Function PrevInst() As Boolean
'Если уже загружена одна копия, не дать повторно загружать вторую
If App.PrevInstance Then
MsgBox "Уже загружена одна копия " & App.Title & "." & vbCrLf & "Нельзя загружать более одной копии.", vbExclamation + vbMsgBoxSetForeground
PrevInst = True
Else 'В противном случае продолеть загрузку
PrevInst = False
End If
End Function
Private Function WaveInPresent() As Boolean
'Получение количества звуковых устройств
If waveInGetNumDevs() > 0 Then 'Если присуствует одно или более устройство
WaveInPresent = True 'То Устройство входа сушествует
Else 'В противном случае
'Сообшим пользоваелю об ошибке
MsgBox "Невозможно определить ниодно устройство ввоза звука." & _
vbCrLf & "Возможно в системе неть звукавой карты или она неисправна." _
, vbCritical, "Ошибка в " & App.Title
WaveInPresent = False 'Как никак, но карты нету (или непонятная)
End If
End Function
Public Sub waveInProc(ByVal hwi&, ByVal uMsg&, ByVal dwInstance&, ByVal dwParam1&, ByVal dwParam2&)
'ВНИМАНИЕ!
'Не вызывайте ниодной системной функции из этой рутины.
'Вызов других звуковых функций можеть вызвать зависание.
'Состояние буфера: заполнен (занят) или нет
If uMsg = MM_WIM_DATA Then bBufferFull = True
End Sub
Private Sub DrawSpect() 'для красоты по разному
'Рисовать спектраль (в главной форме, в елементе pctSpec)
'x% - это длина шкалы (окошка обзора)
'c% - это данные из звукого источника (в виде байтов)
'i% - это просто контейнер для хранения цифр
Dim X%, c%, i%, j%
frmMain.pctSpec.Cls 'Очищаю всё что было нарисовано в яшике рисунка
For X% = 0 To 254 'Начнём круг и возмём все 254 (зачем не 255?)
c% = WaveData(X%) 'Как и описывал, это контейнер звуковых данных
'В зависимости от выбранного стиля рисуем в картинке спектр
With frmMain
Select Case .cmbStyle.ListIndex
Case 0 'Обычный (верхний/полавинчетый)
.pctSpec.Line (X%, c%)-(X%, 256 ), Col(c%)
Case 1 'Осевой - Рисует полную ось: верхюю и нижнию часть
.pctSpec.Line (X%, c%)-(X%, 128), Col(c%)
Case 2 'Точечный - Рисует точку в указаннвх кординатах
.pctSpec.PSet (X%, c%), Col(c%)
Case 3 'Линейный - Рисует лиюнию в до нового кордината от старого кордината
.pctSpec.Line -(X%, c%), Col(c%)
Case 4 'Колечки
.pctSpec.Circle (X%, c%), 2 , Col(c%)
Case 5 'Паралель
.pctSpec.PSet (X%, 112 - c% / 3), vbYellow
.pctSpec.PSet (X%, c% / 3 + 144), vbCyan
Case 6 'Растяжка (линия между двумя точками)
.pctSpec.Line (X%, 128 - c% / 2 )-(X%, c% / 2 + 128 ), Col(c%)
Case 7 'Неатив
.pctSpec.Line (X%, 0)-(X%, c%), Col(c%)
Case Else
End Select
End With
Next X%
End Sub
Public Function Col(CV) As ColorConstants
'Функция для получения цвета в зависимости от звукого банка
Select Case frmMain.cmbColor.ListIndex 'Выбор цвета окраски
Case 0 'Смещанный - Определение по уровню
If CV > 0 And CV 24 And CV 64 And CV 192 And CV 232 And CV 256 Then MsgBox "Хе хе! Бит больше " & CV 'Может и такое быть! :)
Case 1
Col = vbBlue 'Синий
Case 2
Col = vbCyan 'Голубой
Case 3
Col = vbGreen 'Зелённым (по умолч.)
Case 4
Col = vbMagenta 'Лиловый
Case 5
Col = vbRed 'Красный
Case 6
Col = vbWhite 'Белый
Case 7
Col = vbYellow 'Жёлтый
Case Else
End Select
End Function
Public Sub MonitorAudio()
'Мониторинг (наблюдение) за звуком в входном канале
Dim WH As WAVEHDR 'Определим WH как записанный буфер из памяти
waveInStart hWaveIn 'Откуда и как начать
Do 'Начать весь процесс (тот зачем прога создана)
With WH 'Чтоб повторно не писать WH (WAVEHDR) и чтоб не путал каналы
.lpData = VarPtr(WaveData(0)) 'Где взять данные
.dwBufferLength = 256 'Длина буфера (По умолч. 256, но можно и 128)
.dwFlags = 0 'Никаких флажков, чтоб просто работало
End With
waveInPrepareHeader hWaveIn, WH, Len(WH) 'Куда направить, и откуда
bBufferFull = False 'Очисщен буфер, но и контейнер тоже
waveInAddBuffer hWaveIn, WH, Len(WH) 'Добавить звук в буфер
Do 'Начать цикл
DoEvents 'Чтоб не висло...
Loop Until bBufferFull Or hWaveIn = 0 'Пока буфер не переполнен или вход равен нулю
waveInUnprepareHeader hWaveIn, WH, Len(WH) 'Передаём необработанные данные
DrawSpect 'Рисование спектров
DoEvents 'Чтоб не висло и никого не ждало
Loop Until hWaveIn = 0 'Продожить до опусташения
End Sub
Forma
'Данный исходный код демонстрирует как можно получать байты с звукого устройства
'Как определить звуковой спектор
'Как построит простой, половинчетый, линейный и точечный анализатор звукого сигнала
'Как работать с библиотекой "winmm.dll"
'автор кода Алиев Рашид (не я).
Private m As Integer
Private Sub chkOnTop_Click()
'При нажатии мышю изменить расположение окна: повер/не всех окон
If chkOnTop.Value = vbChecked Then 'Если птичка стоит то
'Сделать поверх всех окон (будет всегда стоять на экране)
SetWindowPos frmMain.hwnd, HWND_TOPMOST, 0 , 0 , 0 , 0 , FLAGS
Else
'Вернуть старое расположене окна
SetWindowPos frmMain.hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, FLAGS
End If
End Sub
Private Sub chkX2_Click()
pctSpec.DrawWidth = 1 + chkX2.Value
End Sub
Private Sub cmdAbout_Click()
'Как автор программы имею право на эту кнопку :)
'Задаём текст для ящика "Автор"
MsgBox App.Title & Space(1) & App.Major & "." & App.Minor & vbCrLf & vbCrLf & _
"Автор:" & vbTab & "Рашид Алиев" & vbCrLf & App.Comments & vbCrLf & vbCrLf & "Описание: " & App.FileDescription
End Sub
Private Sub cmdExit_Click()
Unload frmMain 'Передать всё в пункт выгрузки
End Sub
Private Sub cmdStart_Click() 'Запуск всего :)
Dim Rv&
Dim WF As WAVEFORMATEX
cmbStyle.SetFocus
With WF 'Указываем откуда и как читать данные
.wFormatTag = WAVE_FORMAT_PCM 'Формат файла
.nChannels = 1 'Каналы
.nBlockAlign = 1
.nSamplesPerSec = 11025 'Формат 11/22/44 Гц
.wBitsPerSample = 8 'Семпл ( 8 по умолч. но можнои 16 , но сначала надо указать опредеение в SpecAnalyzer)
.nAvgBytesPerSec = (.nSamplesPerSec * .nBlockAlign) \ 8
.cbSize = 0 'Размер буфера (не того о чем вы подумали ;)
End With
'Открыть каналчик и пистаь
Rv = waveInOpen(hWaveIn, WAVE_MAPPER, WF, AddressOf waveInProc, 0 , CALLBACK_FUNCTION)
If Rv 0 Then 'Если нет сигнала
MsgBox "Невозможно открыть устройство ввода звука." & vbCrLf & _
"Возможно он занят или используется другим приложением.", vbCritical, "Ошибка в " & App.Title
Exit Sub 'Просто выйдем
End If
DoEvents 'Чтоб не висло
'Вызваем то зачем всё это создали,
'т.е. модуль чтения и рисования спектрума
MonitorAudio
End Sub
Private Sub cmdStop_Click()
cmbStyle.SetFocus 'Передача фокуса
waveInReset hWaveIn 'Отрубит
waveInStop hWaveIn 'Остановить
waveInClose hWaveIn 'Закрыт
hWaveIn = 0 'Очистить
If chkStopCLS.Value = vbChecked Then pctSpec.Cls
DoEvents 'Чтоб не висло и продолжело работу системы
End Sub
Private Sub Form_Load()
m = 0
cmbStyle.ListIndex = 0
cmbColor.ListIndex = 3
'Даём заголовок из свойства заголовок
frmMain.Caption = App.Title & Space( 1 ) & App.Major & "." & App.Minor
chkOnTop.Value = vbChecked 'Чтоб при запуске был поверх всех (не надо будет кликать)
End Sub
Private Sub Form_QueryUnload(Cancel%, UnloadMode%)
'Отключть монитор и завершить работу программы
'Если остановит возможно (т.е. работает), то остановить (вызвать клик на кнопку стоп)
If cmdStop.Enabled Then cmdStop_Click
Unload frmMain 'Выгрузить форму с памяти
Set frmMain = Nothing 'Очитстить место завнимаемое в ОЗУ
End 'Завершит работу
End Sub
Private Sub pctSpec_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
'При клике на спектрум циркулировать стили
Select Case Button
Case 1
m = m + 1
If m > 7 Then m = 0
Case 2
m = m - 1
If m < 0 Then m = 7
Case Else
End Select
cmbStyle.ListIndex = m
End Sub