PureBoard
https://www.purebasic.fr/german/

ModuleSoundSystem
https://www.purebasic.fr/german/viewtopic.php?f=11&t=11941
Seite 1 von 1

Autor:  NicTheQuick [ 08.02.2007 17:52 ]
Betreff des Beitrags:  ModuleSoundSystem

Hi @ all!

Ich bin gerade dabei einen kleinen Synthesizer zu basteln, den man
irgendwann dann auch mal komfortabel in kleine PureBasic-Projekte
einbinden kann und ein bisschen Musik machen kann.

Den kompletten Quellcode gibt es jetzt noch nicht, weil das ganze noch
lange nicht fertig ist. Aber ein kleiner Vorgeschmack als EXE-Datei und
externer fmodex.dll gibt es hier:
- fmodex.dll
- MSS.exe

Einfach beides in einen Ordner herunterladen und starten. Es öffnet sich
ein Mausklavier, ein Debug-Fenster ohne Debug-Informationen und ein
schwarzes Fenster. Beim Drücken einer Taste sollte dann ein Ton ertönen
und im scharzen Fenster die Welle angezeigt werden. Mit der Tastatur geht
es übrigens auch.

Das Signal ist ein Rechtecksignal (Square), das mit einem Dreiecksignal
(Triangle) amplitudenmoduliert und einem Sinussignal (Sine)
frequenzmoduliert ist. Die Frequenz der Amplitudenmodulation liegt bei
einem Hertz. Die Frequenz der Frequenzmodulation liegt bei 3 Hertz und
ihre Amplitude ist abhängig von der Frequenz des Rechtecksignals mit dem
Multiplikator 0,05.

Soviel zu dem Klang. Hier noch ein Code-Ausschnitt der Main.pb des
Programmes.
Code:
Procedure AmplitudeCallback(time.d, Amplitude.d, Velocity.d, *result.Double)
 
EndProcedure

Procedure.d FrequencyCallback(time.d, Frequency.d, inFrequency.d, Velocity.d)
 
EndProcedure

Procedure EnumMixerInputs(*Wave.MSS_WaveForm)
  ProcedureReturn #True
EndProcedure

Macro Quote
  "
EndMacro
Macro DebugVar(a)
  Debug Quote#a#Quote + ": " + Str(a)
EndMacro
Macro OK(a)
  Debug Quote#a#Quote
  Result = a
  If Result
    Debug FMOD_ErrorString(Result)
    End
  EndIf
EndMacro

Define *IS.ImageScreen, *Keys.Keys
Define Width.l = 1000, Height.l = 400
Define Samplerate.l, Channels.l, exinfo.FMOD_CREATESOUNDEXINFO
Global Dim OnNotes.b(127), Dim NoteSample.l(127), Dim *RefreshOut(127), Dim *FMODOut(127)
Global *Wave.MSS_WaveForm, *Mix.MSS_Mixer

Samplerate = 44100
Channels = 1

Procedure KeyCallback(*Keys.Keys, Note.b, Velocity.b, UserData.l)
  OnNotes(Note) = Velocity
  NoteSample(Note) = 0
EndProcedure
DataSection ;{ Tasten
  Tasten:
    Data.l 25 ;Anzahl aufeinander folgender Noten
    Data.l #VK_Y, #VK_S, #VK_X, #VK_D, #VK_C, #VK_V, #VK_G, #VK_B, #VK_H, #VK_N, #VK_J, #VK_M
    Data.l #VK_Q, #VK_2, #VK_W, #VK_3, #VK_E, #VK_R, #VK_5, #VK_T, #VK_6, #VK_Z, #VK_7, #VK_U, #VK_I
    Data.l -1, -1  ;eins höher/tiefer (-1 = ignorieren)
    Data.l #VK_UP, #VK_DOWN ;eine oktave höher/tiefer
EndDataSection ;}

Procedure RefreshWindow(*IS.ImageScreen)
  Protected x.l, Width.l = *IS\Width(), Height.l = *IS\Height(), yoff.l = Height / 2, oldy.l = yoff, y.d, a.l
  Protected Input.MSS_Input
  Static *Out
 
  If *Out = 0 : *Out = *Wave\NewOut() : EndIf
 
  *IS\StartDraw()
    Box(0, 0, Width, Height, 0)
    For xl = 0 To Width
      y = 0
      For a = 0 To 127
        If OnNotes(a) > 0
          Input\Velocity = OnNotes(a) / 127
          Input\Frequency = 220 * Pow(2, (a - 68) / 12)
          Input\sample = xl * 44100 / Width
          y + *Wave\Out(@Input, *RefreshOut(a))
        EndIf
      Next
      y * -yoff + yoff
      LineXY(xl - 1, oldy, xl, y, $FFFFFF)
      oldy = y
    Next
  *IS\StopDraw()
 
  *IS\ShowChanges()
EndProcedure

Procedure.l Buffercallback(*Sound, *BufferPointer, length.l)
  Protected float.f, *sample.Float, *sample_last, mpos.POINT, a.l
  Protected Input.MSS_Input
  Static *Out
  Shared Channels.l, Samplerate.l
  *sample_last = length + *BufferPointer
  *sample = *BufferPointer
 
  If *Out = 0 : *Out = *Wave\NewOut() : EndIf
 
  Repeat
    float = 0
    For a = 0 To 127
      If OnNotes(a) > 0
        Input\Velocity = OnNotes(a) / 127
        Input\Frequency = 440 * Pow(2, (a - 68) / 12)
        Input\sample = NoteSample(a)
        float + *Wave\Out(@Input, *FMODOut(a))
        NoteSample(a) + 1
      EndIf
    Next
   
    For offset = 1 To Channels
      *sample\f = float
     
      *sample + SizeOf(Float)
    Next
  Until *sample => *sample_last
 
  ProcedureReturn #FMOD_OK
EndProcedure

;{- Wave-Fenster und Keyboard

*IS = IS_New()
*IS\Open(0, 0, Width, Height, "ModuleSoundSystem", 0, #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

*Keys = Keys_New("Mausklavier")
*Keys\Resize(300, 0, 600, 40)
*Keys\AutoAspectRatio(#True)
*Keys\Hide(#False)
*Keys\Callback(@KeyCallback(), 0)
*Keys\SyncInput(#True)
*Keys\SetKeyboard(?Tasten)
*Keys\KeyNote(60)

;}

;{- Waveformen
Define.MSS_WaveForm *Wave1a, *Wave1b, *Wave1, *Wave4
Define.MSS_Mixer *Mix1, *Mix2

*Wave1a = MSS_WaveForm_New()
*Wave1a\Type(#MSS_WaveForm_Sine) ;Sinussignal
*Wave1a\Samplerate(Samplerate)
*Wave1a\Frequency(3) ;Frequenz
*Wave1a\FrequencyType(#MSS_Frequency_Static) ;Frequenz mit Eingangsfrequenz multiplizieren
*Wave1a\Amplitude(0.05) ;Amplitudenhöhe
*Wave1a\AmplitudeType(#MSS_Amplitude_FrequencyMult) ;Amplitudenhöhe mit Eingangsfrequenz multiplizieren
DebugVar(*Wave1a)

*Wave1b = MSS_WaveForm_New()
*Wave1b\Type(#MSS_WaveForm_Triangle) ;Sinussignal
*Wave1b\Samplerate(Samplerate)
*Wave1b\Frequency(1) ;Frequenz
*Wave1b\FrequencyType(#MSS_Frequency_Static) ;Frequenz multiplizieren mit Eingangsfrequenz
*Wave1b\Amplitude(1) ;Amplitudenhöhe
*Wave1b\AmplitudeType(#MSS_Amplitude_Static) ;Amplitudenhöhe mit Eingangslautstärke multiplizieren
*Wave1b\Phase(0.75)
DebugVar(*Wave1b)

*Wave1 = MSS_WaveForm_New()
*Wave1\Type(#MSS_WaveForm_Square) ;Sinussignal
*Wave1\Samplerate(Samplerate)
*Wave1\Frequency(1) ;Frequenz
*Wave1\FrequencyType(#MSS_Frequency_WaveFormAddI) ;Waveform addieren zu Eingangsfrequenz
*Wave1\SetFrequencyCallback(*Wave1a)
*Wave1\Amplitude(0.25) ;Amplitudenhöhe
*Wave1\AmplitudeType(#MSS_Amplitude_WaveformAddVxA) ;Amplitudenhöhe mit Eingangslautstärke multiplizieren
*Wave1\SetAmplitudeCallback(*Wave1b)
DebugVar(*Wave1)

; *Mix1 = MSS_Mixer_New()
; *Mix1\Type(#MSS_Mixing_Average) ;Durchschnittswert aus allen Eingängen nehmen
; *Mix1\Voices(128)
; ;*Mix1\Volume(0.25)
; ;*Mix1\AddInput(*Wave1b, #MSS_Input_WaveForm)
; *Mix1\AddInput(*Wave2, #MSS_Input_WaveForm)
; ;*Mix1\AddInput(*Wave3, #MSS_Input_WaveForm)
; *Mix1\AddInput(*Wave4, #MSS_Input_WaveForm)
; DebugVar(*Mix1)

*Wave = *Wave1
;}

Define a.l
For a = 0 To 127
  *RefreshOut(a) = *Wave\NewOut()
  *FMODOut(a) = *Wave\NewOut()
Next

;{ FMOD initialisieren und Sound starten
Init_FMOD()

OK(FMOD_System_Create(@*System)) ;System erstellen

OK(FMOD_System_Init(*System, Channels, #FMOD_INIT_NORMAL, 0)) ;System initialisieren

With exinfo
  \cbSize = SizeOf(FMOD_CREATESOUNDEXINFO)
  \Numchannels = Channels                     ;Anzahl Kanäle (Stereo)
  \defaultfrequency = Samplerate              ;Die Samplerate (44100)
  \Format = #FMOD_SOUND_FORMAT_PCMFLOAT       ;Das Format (Float)
  \length = Samplerate                        ;Die Länge des Samples (1 Sekunde)
  \decodebuffersize = Samplerate / 20         ;Die Anzahl an Samples pro Callback-Aufruf (25 ms)
  \pcmreadcallback = @Buffercallback()        ;Der Pointer zum Callback
EndWith

;Sample erstellen (2D-Sound, Software-Rendering, Loop)
OK(FMOD_System_CreateSound(*System, 0, #FMOD_2D | #FMOD_OPENUSER | #FMOD_SOFTWARE | #FMOD_CREATESTREAM | #FMOD_LOOP_NORMAL, @exinfo, @*Sound))

;Sound abspielen
OK(FMOD_System_PlaySound(*System, #FMOD_CHANNEL_FREE, *Sound, #False, @*channel))
;}

Repeat
  EventID = WindowEvent()
  *Keys\Event(EventID)
  Select EventID
    Case #PB_Event_CloseWindow
      Break
   
    Case 0
      RefreshWindow(*IS)
      Delay(10)
  EndSelect
  FMOD_System_Update(*System)
ForEver

;{ Sound stoppen und FMOD deinitialisieren
OK(FMOD_Channel_Stop(*channel))
OK(FMOD_Sound_Release(*Sound))
OK(FMOD_System_Release(*System))

*IS\Kill()
*Wave1\Kill()

End
;}

Autor:  dige [ 09.02.2007 09:50 ]
Betreff des Beitrags: 

Schon mal ganz putzig das Ganze. Der hohe Ton klingt aber wie ein
altes Radio beim Sender suchen ;-)

Autor:  Tafkadasom2k5 [ 09.02.2007 10:59 ]
Betreff des Beitrags: 

dige hat geschrieben:
Schon mal ganz putzig das Ganze. Der hohe Ton klingt aber wie ein
altes Radio beim Sender suchen ;-)
Das liegt an deiner Soundkarte zusammen mit deinen Boxen. Wenn die Tonhöhe die deiner Soundkombi überschreitet, versucht die Hardware das so zu oktavieren, das es klappt. Die Schwingungen, die du dabei vernimmst, klingen halt komisch. ABer wenn du genau hinhörst ist es der gleiche Ton, nur eben auf anderer Tonbasis.

Gr33tz
Tafkadasom2k5

Autor:  bobobo [ 09.02.2007 13:03 ]
Betreff des Beitrags: 

und ich suche gerade ein DigitalPiano ..
@Nick wenn Dein Programm fertig ist dann schenkst Du mir sicher Dein
Yamaha CLP irgendwas, oder?

Autor:  NicTheQuick [ 11.02.2007 22:35 ]
Betreff des Beitrags: 

Mein YAMAHA CLP? Hab ich keins. Oder gibts das gar net? <)

Ich hab jetzt noch ein Mixer-Modul gebaut, dann kommt noch ein Sampler
und ein Hüllkurvenmodul.
Mal schauen, was mir noch so alles einfällt. :D

Danach kommt eine kleine GUI, mit der man sich dann ein paar Sounds
zusammenstöpseln kann. Und dann eine Art Play-Befehl, mit der man Musik
spielen lassen kann. :)

Autor:  dllfreak2001 [ 11.02.2007 22:59 ]
Betreff des Beitrags: 

Kommt dieser Effekt nicht eher dadurch das die Abtastrate zu gering ist?

Naja, an den Boxen liegt es jedenfalls nicht, nur an der Soundkarte.

Autor:  DarkSoul [ 12.02.2007 16:22 ]
Betreff des Beitrags: 

Zitat:
Naja, an den Boxen liegt es jedenfalls nicht, nur an der Soundkarte.



em ste ich voll zu, denn die boxen spucken nur das aus, was elektrisch reinkommt, nur halt lauter :wink: Die kennen keine Abtastraten oder Bitzahlen, nur nen frequenzgang (von wo bis wo), ne ohmzahl (bei pc-boxen unwchtig, da da schon ne endstufe drinne is), nen wirkungsgrad (die wichtigste angabe) und ne wattzahl (wieviel strom das ganze verschlingt, nicht unbedingt lautstärkerelevant)
Es sei denn man hat digitale eingänge, aber das sind höherwertigere, die whl kaum die blechdosen-22050hz x 8bit als maximum haben

Seite 1 von 1 Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/