Точняк,я просто вчера попробовал без отладчика и в код не вникал
Миди синтезатор
Сообщений 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)