PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Программирование на PureBasic » Миди синтезатор


Миди синтезатор

Сообщений 31 страница 36 из 36

31

Точняк,я просто вчера попробовал без отладчика и в код не вникал

0

32

Кстати, о синтезе

Код:
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, теперь звук затыкается при любом событии окна - перетаскивание окна или нажатие на гаджет. В чем причина я не знаю.

0

33

Так затыкается что работает в одном потоке событий с окном,надо делать в отдельном потоке или через таймер коды которых выше.они тоже свой поток создают.

Отредактировано Sergeihik (28.09.2021 09:45:39)

0

34

Sergeihik написал(а):

Так затыкается что работает в одном потоке событий с окном,надо делать в отдельном потоке или через таймер коды которых выше.они тоже свой поток создают.

Какие потоки? Сообщения прилетают процедуре окна.

0

35

В общем, перемудрил или я или дядя, который писал

Код:
#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)                                  ;

0

36

Вот как вариант ещё.только надо правильно структуру данными заполнять.

Код:
#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)

0


Вы здесь » PureBasic - форум » Программирование на PureBasic » Миди синтезатор