Точняк,я просто вчера попробовал без отладчика и в код не вникал
Миди синтезатор
Сообщений 31 страница 36 из 36
Поделиться3228.09.2021 06:44:33
Кстати, о синтезе
Enumeration
#sb
#st
EndEnumeration
#FREQ_MIN = 20
#FREQ_MAX = 8000
#FREQ_STEP = 1
#FREQ_INIT = 221
#SAMPLE_RATE = 22050; ' Possible values: 44100, 22050, 11025, 8000
#OUT_BUFFER_SIZE = 128*2; ' Size of buffers (if 16-bit, be sure that %OUT_BUFFER_SIZE/2 is an integer )
#NUM_BUF = 48-41; ' Numbers of buffers
#BIT16 = 1 ; ' %BIT16 defined implies 16-bit, %BIT16 not defined implies 8-bit
CompilerIf Defined(BIT16, #PB_Constant)
#BITS = 16
Procedure FillBuffer(*pBuffer,iFreq.f)
fAngle.f=0
For i = 0 To #OUT_BUFFER_SIZE - 1
PokeU(*pBuffer+i*2,Int(30000 * Sin( fAngle )))
fAngle = fAngle + 2 * #PI * iFreq / #SAMPLE_RATE
If fAngle > 2 * #PI
fAngle = fAngle - 2 * #PI
EndIf
Next i
EndProcedure
CompilerElse
#BITS = 8
Procedure FillBuffer(*pBuffer,iFreq.f)
fAngle.f
For i = 0 To #OUT_BUFFER_SIZE-1
PokeA(*pBuffer+i,Int(127 + 127 * Sin( fAngle )))
fAngle = fAngle + 2 * #PI * iFreq / #SAMPLE_RATE
If fAngle > 2 * #PI
fAngle = fAngle - 2 * #PI
EndIf
Next i
EndProcedure
CompilerEndIf
Global Dim zBuffer(#NUM_BUF-1)
Global Dim WaveHeader.WAVEHDR(#NUM_BUF-1)
Global WvFormat.WAVEFORMATEX
Global hWaveOut=0
Global bShutOff
For i=0 To #NUM_BUF-1
zBuffer(i)=AllocateMemory(#OUT_BUFFER_SIZE*2+2)
Next i
iFreq.f = #FREQ_INIT
If OpenWindow(0, 0, 0, 305, 140, "ScrollBarGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScrollBarGadget(#sb, 10, 42, 250, 20, 0, 100, 30)
ButtonGadget(#st,10,80,290,20,"st")
Repeat
ev=WaitWindowEvent()
Select ev
Case #MM_WOM_DONE
If bShutOff
waveOutClose_(hWaveOut)
End;EXIT FUNCTION
EndIf
; ' Fill and send out a new buffer
*pWaveHdr.WAVEHDR = EventlParam();CBLPARAM
FillBuffer(*pWaveHdr\lpData, iFreq)
;Debug *pWaveHdr\lpData
r.l=waveOutWrite_(hWaveOut,*pWaveHdr, SizeOf(WAVEHDR))
Case #MM_WOM_CLOSE
For i = 0 To #NUM_BUF-1
waveOutUnprepareHeader_(hWaveOut, @WaveHeader(i), SizeOf(WAVEHDR))
Next i
hWaveOut = 0
Case #MM_WOM_OPEN
;Send buffers to output device
For i = 0 To #NUM_BUF-1
FillBuffer(zBuffer(i), iFreq)
waveOutWrite_( hWaveOut, @WaveHeader(i), SizeOf(WAVEHDR))
Next i
Case #PB_Event_Gadget
Select EventGadget()
Case #st
If hWaveOut = 0;Variable to indicate Off button pressed
bShutOff = #False
;' Open waveform audio for output
nChannels=1
nSamplesPerSec= #SAMPLE_RATE
wBitsPerSample=#BITS
WvFormat\wFormatTag = #WAVE_FORMAT_PCM
WvFormat\nChannels = nChannels
WvFormat\nSamplesPerSec = nSamplesPerSec
WvFormat\nAvgBytesPerSec = nSamplesPerSec * nChannels * wBitsPerSample / 8
WvFormat\nBlockAlign = nChannels * wBitsPerSample / 8
WvFormat\wBitsPerSample = wBitsPerSample
WvFormat\cbSize = 0
If waveOutOpen_(@hWaveOut, #WAVE_MAPPER, @WvFormat, WindowID(0), 0, #CALLBACK_WINDOW) <> #MMSYSERR_NOERROR
hWaveOut = 0
Debug "Error opening waveform audio device!"
End
EndIf
;' Set up headers and prepare them
For i = 0 To #NUM_BUF-1
WaveHeader(i)\lpData = zBuffer(i)
WaveHeader(i)\dwBufferLength = #OUT_BUFFER_SIZE
WaveHeader(i)\dwBytesRecorded = 0
WaveHeader(i)\dwUser = 0
WaveHeader(i)\dwFlags = #WHDR_BEGINLOOP | #WHDR_ENDLOOP
WaveHeader(i)\dwLoops = 10
WaveHeader(i)\lpNext = 0
WaveHeader(i)\Reserved = 0
waveOutPrepareHeader_(hWaveOut, @WaveHeader(i), SizeOf(WAVEHDR))
Next i
;' If turning off waveform, reset waveform audio
Else
bShutOff = #True
waveOutReset_(hWaveOut)
EndIf
EndSelect
EndSelect
Until ev = #PB_Event_CloseWindow
EndIf
For i=0 To #NUM_BUF-1
FreeMemory(zBuffer(i))
Next i
взялся за порт кода из PowerBasic, теперь звук затыкается при любом событии окна - перетаскивание окна или нажатие на гаджет. В чем причина я не знаю.
Поделиться3328.09.2021 09:44:43
Так затыкается что работает в одном потоке событий с окном,надо делать в отдельном потоке или через таймер коды которых выше.они тоже свой поток создают.
Отредактировано Sergeihik (28.09.2021 09:45:39)
Поделиться3428.09.2021 09:52:46
Так затыкается что работает в одном потоке событий с окном,надо делать в отдельном потоке или через таймер коды которых выше.они тоже свой поток создают.
Какие потоки? Сообщения прилетают процедуре окна.
Поделиться3528.09.2021 10:23:32
В общем, перемудрил или я или дядя, который писал
#SAMPLE_RATE=44100
Global FREQUENCY.f=1000
#BLOCK_SIZE=4000
#MAX_NUM=$7f;ff; // максимальный short
Enumeration
#fsb
EndEnumeration
Global wave.l
Global hdr1.WAVEHDR
Global hdr2.WAVEHDR
Global iHdr = 1;
Global time = 0;
Global *data1=AllocateMemory(#BLOCK_SIZE)
Global *data2=AllocateMemory(#BLOCK_SIZE)
Procedure calcbuf(*d)
For t = 0 To #BLOCK_SIZE-1
PokeA(*d+t,Int( Sin((time + t) * 2 * #PI * FREQUENCY / #SAMPLE_RATE) * #MAX_NUM) ); // 2*PI
Next t
EndProcedure
Procedure waveOutCallBack(hWave.l, msg.l, inst.l, param1.l, param2.l)
If msg = #WOM_DONE
If iHdr = 1
calcbuf(*data1)
waveOutWrite_(hWave, @hdr1, SizeOf(WAVEHDR));
iHdr = 2 ;
Else
calcbuf(*data2)
waveOutWrite_(hWave, @hdr2, SizeOf(WAVEHDR));
iHdr = 1 ;
EndIf
time=time+#BLOCK_SIZE;
EndIf
EndProcedure
Procedure freqback()
FREQUENCY=GetGadgetState(#fsb);/15
SetWindowTitle(0,Str(GetGadgetState(#fsb)))
EndProcedure
wForm.WAVEFORMATEX
wForm\wFormatTag = #WAVE_FORMAT_PCM;
wForm\nChannels = 1 ;
wForm\nSamplesPerSec = #SAMPLE_RATE;
wForm\wBitsPerSample = 16
wForm\nBlockAlign = wForm\nChannels * wForm\wBitsPerSample / 8;
wForm\nAvgBytesPerSec = wForm\nSamplesPerSec * wForm\nBlockAlign;
wForm\cbSize = 0
waveOutOpen_(@wave, #WAVE_MAPPER, @wForm, @waveOutCallBack(), 0, #CALLBACK_FUNCTION| #WAVE_FORMAT_DIRECT);
hdr1\lpData = *data1;
hdr1\dwBufferLength = #BLOCK_SIZE ;SizeOf(short); // размер в байтах в два раза больше количества семплов
hdr2\lpData = *data2;
hdr2\dwBufferLength = #BLOCK_SIZE ;SizeOf(short); // размер в байтах в два раза больше количества семплов
waveOutPrepareHeader_(wave, @hdr1, SizeOf(WAVEHDR));
waveOutPrepareHeader_(wave, @hdr2, SizeOf(WAVEHDR));
calcbuf(*data1)
calcbuf(*data2)
iHdr = 1;
time = time+#BLOCK_SIZE * 2;
waveOutWrite_(wave, @hdr1, SizeOf(WAVEHDR));
waveOutWrite_(wave, @hdr2, SizeOf(WAVEHDR));
If OpenWindow(0, 0, 0, 300, 90, "synth sinwave", #PB_Window_SystemMenu | #PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
ScrollBarGadget(#fsb,0,10,290,20,221,8000,5)
BindGadgetEvent(#fsb, @freqback())
Repeat
Event = WaitWindowEvent()
Select Event
EndSelect
Until Event = #PB_Event_CloseWindow
EndIf
waveOutUnprepareHeader_(wave, @hdr1, SizeOf(WAVEHDR));
waveOutUnprepareHeader_(wave, @hdr2, SizeOf(WAVEHDR));
waveOutClose_(wave) ;
Поделиться3603.10.2021 23:15:26
Вот как вариант ещё.только надо правильно структуру данными заполнять.
#SAMPLE_RATE=44100
Global FREQUENCY.f=1000
#BLOCK_SIZE=4000
#MAX_NUM=$7fff;ff;
Enumeration
#fsb
EndEnumeration
Global wave.i
Global hdr1.WAVEHDR
Global hdr2.WAVEHDR
Global time = 0;
Procedure calcbuf_sin(*d)
Protected r.f
For t = 0 To (#BLOCK_SIZE-2)/2 Step 2
PokeW(*d+t,Int( Sin(r)*FREQUENCY)*20 );
r+0.17
Next t
EndProcedure
Procedure waveOutCallBack(hWave.i, msg.i, Instance.i, param1.i, param2.i)
Static iHdr.a
If msg = #WOM_DONE;Отправляется, когда драйвер устройства завершает работу с блоком данных, отправленным с помощью функции waveOutWrite
If iHdr = 1
;calcbuf_sin(hdr1\lpData)
waveOutWrite_(hWave, @hdr1, SizeOf(WAVEHDR));
iHdr = 2 ;
ElseIf iHdr=2
;calcbuf_sin(hdr2\lpData)
waveOutWrite_(hWave, @hdr2, SizeOf(WAVEHDR));
iHdr = 1 ;
EndIf
;time+#BLOCK_SIZE-1;
ElseIf msg=#WOM_CLOSE; Отправляется, когда устройство закрывается с помощью функции waveOutClose
FreeMemory(hdr1\lpData)
FreeMemory(hdr2\lpData)
ElseIf msg=#WOM_OPEN ;Отправляется, когда устройство открывается с помощью функции waveOutOpen
iHdr = 1
hdr1\lpData=AllocateMemory(#BLOCK_SIZE)
hdr1\dwBufferLength = #BLOCK_SIZE
; hdr1\dwFlags=#WHDR_BEGINLOOP | #WHDR_ENDLOOP
;hdr1\dwLoops=1000
calcbuf_sin(hdr1\lpData)
hdr2\lpData =AllocateMemory(#BLOCK_SIZE)
hdr2\dwBufferLength = #BLOCK_SIZE
; hdr1\dwFlags=#WHDR_BEGINLOOP | #WHDR_ENDLOOP
;hdr1\dwLoops=1000
calcbuf_sin(hdr2\lpData)
EndIf
EndProcedure
Procedure freqback()
FREQUENCY=GetGadgetState(#fsb);/15
SetWindowTitle(0,Str(GetGadgetState(#fsb)))
calcbuf_sin(hdr1\lpData)
calcbuf_sin(hdr2\lpData)
EndProcedure
;Структура WAVEFORMATEX определяет формат звуковых данных формы волны. В эту структуру включается только информация о формате,
;общая для всех форматов звуковых данных. Для форматов, требующих дополнительной информации, эта структура включается в качестве первого члена в
;другую структуру вместе с дополнительной информацией.
;Форматы, которые поддерживают более двух каналов или размеры выборки более 16 бит, могут быть описаны в структуре WAVEFORMATEXTENSIBLE,
;которая включает структуру WAVEFORMAT.
pcmFormat.WAVEFORMATEX;
pcmFormat\wFormatTag = #WAVE_FORMAT_PCM;
pcmFormat\nChannels = 1;Количество каналов в аудиоданных осциллограммы. Монофонические данные используют один канал, а стереоданные - два канала.
pcmFormat\nSamplesPerSec = #SAMPLE_RATE;
pcmFormat\wBitsPerSample = 16;Количество бит на выборку
pcmFormat\nBlockAlign = pcmFormat\nChannels * pcmFormat\wBitsPerSample / 8;
pcmFormat\nAvgBytesPerSec = pcmFormat\nSamplesPerSec * pcmFormat\nBlockAlign;
pcmFormat\cbSize = 0
If waveOutOpen_(@wave, #WAVE_MAPPER, @pcmFormat, 0, 0, #WAVE_FORMAT_QUERY)=0;проверка поддержки формата
waveOutOpen_(@wave, #WAVE_MAPPER, @pcmFormat, @waveOutCallBack(), 0, #CALLBACK_FUNCTION| #WAVE_FORMAT_DIRECT);
waveOutPrepareHeader_(wave, @hdr1, SizeOf(WAVEHDR));
waveOutPrepareHeader_(wave, @hdr2, SizeOf(WAVEHDR));
waveOutWrite_(wave, @hdr1, SizeOf(WAVEHDR));
waveOutWrite_(wave, @hdr2, SizeOf(WAVEHDR));
EndIf
If OpenWindow(0, 0, 0, 300, 90, "synth sinwave", #PB_Window_SystemMenu | #PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
ScrollBarGadget(#fsb,0,10,290,20,221,8000,5)
BindGadgetEvent(#fsb, @freqback())
Repeat
Event = WaitWindowEvent()
Select Event
EndSelect
Until Event = #PB_Event_CloseWindow
EndIf
waveOutUnprepareHeader_(wave, @hdr1, SizeOf(WAVEHDR));
waveOutUnprepareHeader_(wave, @hdr2, SizeOf(WAVEHDR));
;waveOutReset_(wave)
waveOutClose_(wave)