MIDI-TO-OGG Konverter

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

Midimaster

Betreff: MIDI-TO-OGG Konverter

BeitragMo, Mai 30, 2011 11:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Im Rahmen meines Rhythmus-Trainer Projektes musste ich feststellen, dass es auf dem MAC überhaupt kein Standard-MIDI-Device ala "Microsoft GS WaveTable" gibt. Das heißt jeder Sound der dort erklingen soll, muss als Audio-Datei mitgegeben werden.

Ein WaveTable dagegen stellt ein Minimum von 127 frei spielbaren Musik-Instrumenten, sowie ca 40 Drum-Sounds zur Verfügung. Diese Instrumente decken den gesamte Bandbreite an Musikinstrumenten ab und Du kannst damit jede Note auf jeden Instrument spielen.

Meine Idee war nun, auf einen WIN-Rechner einfach den gesamten WaveTable Sound für Sound, Note für Note abzuräumen und in einzelnen Ogg-Sounds zur Verfügung zu stellen. Genau dies ermöglicht der MIDI-TO-OGG Konverter. Ideales Tool auch für Monkey-Projekte.
user posted image
Fertige Exe: http://www.midimaster.de/downl...verter.exe

Es ist z.B. mit dem Tool möglich 40 Drum-Sounds automatisch zu generieren und sie dann als OGG-Sounds im eigenen Programm wieder zu einen Beat zusammenzusetzen. Oder Du kannst z.b. 24 Töne einer Gitarre generieren lassen und dann beliebige Gitarrenmelodien in deinem Code abspielen.

Natürlich kannst Du das Programm auch mit einem hochwertigem MIDI- Keyboard zusammenarbeiten lassen. Dann bist Du in der Lage den Sound des Instrumentes Ton für Ton auf den Computer zu transferieren. So kommt Du an hochwertige Sound für deine Spiele.


Anleitung der neuen Version II:

Nach dem Einstellen des MIDI-Device, sowie Auswahl der MIDI-Kanals (10=Drums, alle anderen sind Sounds) wählst Du eines der 127 Instrumente aus.

Nun legst Du fest, von welcher tiefen Note bis zu welcher hohen Note Einzelsounds erstellt werden sollen. Theoretisch reichen die Werte von 0 bis 127. Praktisch wird man nur Sound zwischen 24 und 96 hörbar wahrnehmen. Der Ton C=36, C#=37, D=38... , c=48, ..., c'=60, ... Achting beim Drum-Channel 10 sind möglicherweise alle 127 nützlich!

Mit dem Midi-Volumen legt man vor allem fest, wie agressiv der Sound klingen soll. Das Midi-Volumen verändert zwar auch die Lautstärke des zu spielenden Sounds, aber vor allem die Agressivität. Vol=60 ist "normal".

Die Sample Länge legt fest, in welcher Länge Du die Sound benötigst. Es sind Werte möglich von 500msec bis 5000msec.

Viele Sound klingen "nach" oder haben nach dem Loslassen noch Hall. Mit dem "Back Cut" Threshold Wert legst Du fest, ob die Aufnahme hinten so beschnitten werden soll, dass nur der Teil der eine Mindestlautstärke aufweist als Sound gespeichert werden soll. Mit Werten wie "0" bekommst Du die gesamte Samplelänge +eventuel bis zu 2sec wegen eines Nachhalls. Mit Werten wie "100" wird solch ein Hall so gut wie völlig herausgeschnitten.

Der "Front Cut" Threshold schneidet stille Teile vorne in der Aufnahme ab. Manche MIDI-Soundmodule benötigen etliche msec, bevor sie endlich den Sound abspielen. Ein "Front Cut" Threshold von 250 sorgt dafür dass der gespeicherte Sound keinen unnötigen "Vorspann" mehr enthält und die Sounds später im Spiel sofort mit etwas lauten starten.


Mit dem Button "Test" kannst Du nun die Konvertierung simulieren, mit dem Button "Save" geht es los. Die Sounds werden der Reihe nach abgespielt und dann unter "Eigene Dateien" in einem gemeinsamen Ordner gesammelt.

Wichtig:

Die Lautstärke der Aufnahme wird mit dem Windows-Mixer kontrolliert. Hierzu muss im Mixer bei Optionen die Eigenschaft auf "Aufnahme" gestellt werden und als Quelle der "Stereo-Mix" verwendet werden. Mach zuerst Probeaufnahmen und betrachte die entstandenen OGG-Files in Audacity auf Übersteuerung. Die Lautstärke des Audiomaterials sollte nur bis zu etwa 50% ausgereizt werden.



Hier der Quellcode (allerdings der alten Version):

BlitzMax: [AUSKLAPPEN]
SuperStrict

Import BaH.RtMidi

Import axe.oggsaver ' *) kann weggelassen werden (siehe Projektseite bei blitzforum.de)
Import BaH.Volumes ' *) kann weggelassen werden (siehe "Pfad$ =....")
Import MaxGUI.Drivers ' *) kann weggelassen werden (siehe Projektseite bei blitzforum.de)

'GUI:
Global Window:TGadget , ComboBox:TGadget, Slider:TGadget[10] , SliderCaption:TGadget[10] , Textfield:TGadget[10]
Global Label:TGadget , Button:TGadget , TestButton:Tgadget , StopButton:Tgadget, ComboBoxDevice:TGadget
Const START_NOTE%=0 , END_NOTE%=1 , MIDI_VOLUME%=2 , MIDI_Kanal%=3 , TON_LANG%=4
Global TextDatei:TGadget

'eigene:

Global Anzahl%, HolZeit%, AufnahmeAn%=0 , Spuren%=2 , Aufloesung%=2 , Zeit% , DeviceNr%=0 , MinimumSampleGroesse%=4000
Global GesamtSpeicherPlatz%= 44100 * Spuren * Aufloesung% * 6 ' 6 sec max!
Global Klang:TAudioSample=CreateAudioSample(GesamtSpeicherPlatz , 44100 , SF_STEREO16LE)
Global StartTon%=60, Ton%, EndTon%=72, Kanal%=1 , Laut%=90 , Mode%=-1 , Lang%=2000 ,Warte%=500, Instrument%=0 , SampleName$
Global Pfad$=""


'auskommentieren und Bah.Volume wird nicht mehr benötigt
Pfad$ = GetUserDocumentsDir() + "\"




'MIDI und OpenAL:

Global midiOut:TRtMidiOut = New TRtMidiOut.Create()
Global message:Byte[] = New Byte[3]
Global CaptureDevice% , Device%




OpenMidi
Open_OpenAl
FensterErstellen


CreateTimer 60
While WaitEvent()
'Print EventID()
Select EventID()
Case EVENT_TIMERTICK
HauptSchleife

Case EVENT_GADGETPAINT

Case EVENT_WINDOWCLOSE
ProgrammEnde

Case EVENT_APPTERMINATE
ProgrammEnde

Case EVENT_MENUACTION

Case EVENT_GADGETACTION
Local locWert%=EventData()
Local tmpGadget:TGadget = TGadget(EventSource())
If tmpGadget
If (Slider[START_NOTE] = tmpGadget) Or (TextField[START_NOTE] = tmpGadget)
SetMySliderValue START_NOTE , locWert
If locWert >= SliderValue(Slider[END_NOTE])
SetMySliderValue END_NOTE , locWert+1
EndIf
StartTon=locWert
ElseIf (Slider[END_NOTE] = tmpGadget) Or (TextField[END_NOTE] = tmpGadget)
If locWert <= SliderValue(Slider[START_NOTE])
locWert = SliderValue(Slider[END_NOTE])+1
EndIf
SetMySliderValue END_NOTE , locWert
ElseIf (Slider[MIDI_KANAL] = tmpGadget) Or (TextField[MIDI_KANAL] = tmpGadget)
SetMySliderValue MIDI_KANAL , locWert
AendereComboBox(locWert)
ElseIf (Slider[MIDI_VOLUME] = tmpGadget) Or (TextField[MIDI_VOLUME] = tmpGadget)
SetMySliderValue MIDI_VOLUME , locWert
ElseIf (Slider[TON_LANG] = tmpGadget) Or (TextField[TON_LANG] = tmpGadget)
locWert=Int(locWert/100)*100
SetMySliderValue TON_LANG , locWert
ElseIf TestButton = tmpGadget
Print "SIMULATE :" + pfad + GadgetText(ComboBox) + "\"
StarteProzess(1)
ElseIf Button = tmpGadget
Print "Save All Files :" + pfad + GadgetText(ComboBox) + "\"
StarteProzess(0)
ElseIf StopButton = tmpGadget
If Mode>0 Then
alcCaptureStop(CaptureDevice)
SpielTon Ton, 0, Kanal
EndIf
AufnahmeAn=0
midiOut.closePort()
Mode=-1
EndIf
EndIf
End Select
Wend
ProgrammEnde



Function HauptSchleife()
If (HolZeit<MilliSecs())
If AufnahmeAn=1
Print "Aufnahme läuft"
ElseIf AufnahmeAn=2
Print "Simulation läuft"
EndIf
HolZeit=MilliSecs() +500
EndIf

If Zeit<MilliSecs()
Select Mode
Case 0
Mode=1
alcCaptureStart(CaptureDevice)
Delay 50
SetGadgetText label, SampleName + Ton + ".Ogg"
'play
SpielTon Ton, Laut, Kanal
Zeit=Zeit + Lang

Case 1
Mode=2
'stop
SpielTon Ton, 0, Kanal
Zeit=Zeit+ Warte
Case 2
'record
alcCaptureStop(CaptureDevice)
HoleAlleSamplesAb
Zeit=Zeit+ Warte
Ton=Ton +1
If Ton =EndTon
BeendeProzess
Else
Mode=0
EndIf
End Select
EndIf

End Function






'************** GUI FUNKTIONEN *****************************************





Function FensterErstellen()
Local flags%=WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS|WINDOW_CENTER
Window= CreateWindow("GS-TO-OGG Converter" , 0 , 0 , 240 , 500 , Null , Flags%)

ComboBoxDevice=CreateComboBox(20 , 10 , 200,30,window )

CreateMySlider MIDI_KANAL , "MIDI-Kanal" , 80 , 50 , window , 1 , 16 , 1
ComboBox = CreateComboBox(20 , 90 , 200 , 30 , window )
CreateMySlider START_NOTE , "Start-Note" , 80 , 130 , window , 12 , 120 , 60
CreateMySlider END_NOTE , "End-Note" , 80 , 170 , window , 37 , 84 , 72
CreateMySlider MIDI_VOLUME , "MIDI-Volume" , 20 , 220 , window , 40 , 120 , 90 , 1
CreateMySlider TON_LANG , "Sample Länge" , 20 , 290 , window , 500 , 5000 , 2000 , 1
Label = CreateLabel ("You listen to..." , 20 , 340 , 200 , 20 , window, LABEL_CENTER|LABEL_SUNKENFRAME)
TestButton = CreateButton ("Test" , 20 , 390 , 60 , 40 , window)
Button = CreateButton ("Save" , 90 , 390 , 60 , 40 , window)
StopButton = CreateButton ("Stop" , 160 , 390 , 60 , 40 , window)
Kanal=9
AendereComboBox(1)
Kanal=1

For Local i%=0 To 10
Local loc$
If i = midiOut.getPortCount() Then Exit
loc= midiOut.getPortName(i)
Print i + ". Add MIDI OUT DEVICE =" + loc + "!"
AddGadgetItem ComboBoxDevice,loc
Next
SelectGadgetItem ComboBoxDevice,0

End Function





Function CreateMySlider(Nr% , Caption$ , X% , Y%, Mother:TGadget , Mini% , Maxi% , Wert% , Typ%=0 )
If Typ=0 Then
SliderCaption[nr]=CreateLabel( Caption+" " , X-150, Y+3, 150 , 20, Mother, LABEL_RIGHT)
Slider[Nr] = CreateSlider ( X , Y , 32 , 26 , Mother,SLIDER_HORIZONTAL|SLIDER_STEPPER)
TextField[Nr] = CreateTextField ( X+32 , Y , 30 , 20 , Mother)

Else
SliderCaption[nr] = CreateLabel( Caption, X+10, Y+22, 120 , 20, Mother, LABEL_CENTER)
Slider[Nr] = CreateSlider ( X , Y , 150 , 50 , Mother,SLIDER_HORIZONTAL|SLIDER_TRACKBAR)
TextField[Nr] = CreateTextField ( X+150 , Y+10 , 40 , 20 , Mother)
EndIf
SetSliderRange Slider[Nr] ,Mini , Maxi
SetSliderValue Slider[Nr] , Wert
SetGadgetText TextField[Nr], Wert
End Function





Function SetMySliderValue( Nr% , Wert% ,negativ%=0 )
SetSliderValue Slider[Nr] , Wert
SetGadgetText TextField[Nr], Wert
End Function




Function AendereComboBox(NeuKanal%)
Local i%, Zeile$ , Stream:TStream
If (NeuKanal=10) And (Kanal<>9)
ClearGadgetItems ComboBox
AddGadgetItem ComboBox ,"Drum Sounds"
Kanal=9
ElseIf (NeuKanal<>10) And (Kanal=9)
ClearGadgetItems ComboBox
Stream=OpenFile("GMSound.lst")
While Eof(Stream)=0
Zeile=ReadLine(Stream)
Print zeile
AddGadgetItem ComboBox , Zeile
Wend
CloseFile Stream
Kanal=NeuKanal-1
EndIf
SelectGadgetItem ComboBox,0
End Function





'************** AUDIO UND MIDI FUNKTIONEN *****************************************




Function OpenMidi()
If midiOut.getPortCount() = 0 Then
RuntimeError "Kein MIDI-OUT vorhanden!"
End If
Print "Opening " + midiOut.getPortName()
End Function




Function Open_OpenAl()
' OpenAl-Check und Start
If OpenALInstalled()=False Then
RuntimeError "Bitte OpenAL installieren!"
EndIf

EnableOpenALAudio()
SetAudioDriver("OpenAL")

Device=alcOpenDevice(Null)
If Device=Null Then
RuntimeError "Kein Zugriff auf Open-AL-Device möglich!"
EndIf

If (alcIsExtensionPresent(Device, "ALC_EXT_CAPTURE") = AL_FALSE) Then
RuntimeError "Kein Recording möglich!"
EndIf

CaptureDevice = alcCaptureOpenDevice(Null, 44100, AL_FORMAT_STEREO16, 44100*2*2*6);
If Not(CaptureDevice) Then
RuntimeError "Kein Zugriff auf Open-AL-CAPTURE-Device möglich!"
EndIf

EndFunction





Function ProgrammEnde()
If Mode > 0
SpielTon Ton, 0, Kanal
EndIf
midiout.Free

alcCaptureStop(CaptureDevice)
alcCloseDevice(CaptureDevice)
alcCloseDevice(Device)
End
End Function





Function EraseSample()
Local i%
Print "erase"
For I=0 To 44100*4*5-1
Klang.Samples[i]=0
Next
End Function






Function SpielTon (Ton%, Laut% , Kanal%)
message[0] = 144 + Kanal
message[1] = Ton
message[2] = Laut
midiout.putMessage(message, 3)
End Function







Function ProgrammChange()
message[0] = 192+Kanal
message[1] = Instrument
message[2] = 0
midiout.putMessage(message, 2)
End Function




Function StarteProzess(Simulation%)
Zeit = MilliSecs()+500

If Simulation=1 Then
AufnahmeAn=2
Else
AufnahmeAn=1
EndIf
DeviceNr = SelectedGadgetItem(ComboBoxDevice)
midiOut.openPort(DeviceNr)

StartTon = SliderValue(Slider[START_NOTE])
EndTon = SliderValue(Slider[END_NOTE])
Kanal = SliderValue(Slider[MIDI_KANAL])-1
Laut = SliderValue(Slider[MIDI_VOLUME])
Lang = SliderValue(Slider[TON_LANG])
Instrument = SelectedGadgetItem(ComboBox)
SampleName= GadgetText(ComboBox)
CreateDir Pfad + SampleName
Delay 100
ProgrammChange()
Ton=StartTon
Mode=0
End Function





Function BeendeProzess()
AufnahmeAn=0
midiOut.closePort()
Delay 200
Mode=-1
End Function



Function HoleAlleSamplesAb()
Local KlangFinish:TAudioSample
Local StartPos%, EndPos% , i%, j% , Sum% , Wo%

'abholen:
EraseSample()
alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 4, Varptr(Anzahl))
Print Anzahl + " Samples stehen bereit"
If (Anzahl*Spuren*Aufloesung) < GesamtSpeicherPlatz Then
alcCaptureSamples(CaptureDevice, Klang.Samples, Anzahl)
Print "Samples kopiert "
EndIf

'Volumen berechnen und SchneideMarke START finden:
For i=0 To GesamtSpeicherPlatz Step 200
Sum=0
For j=0 To 399 Step 4
Wo= i + j + 1
If Klang.samples[wo]<128 Then
sum=sum+Klang.samples[wo]
EndIf
Next
If sum>500
StartPos = i
Exit
EndIf
Next
EndPos=StartPos+200

'Volumen berechnen und SchneideMarke ENDE finden:
For i = Int(GesamtSpeicherPlatz/400-1)*400 To 0 Step -200
sum=0
For j=0 To 399 Step 4
Wo= i + j + 1
If Klang.samples[wo]<128 Then
sum=sum+Klang.samples[wo]
EndIf
Next
If sum>250
EndPos = i+ 400
Exit
EndIf
Next
Print "Startpos " + startpos
Print "Endpos " + endpos

' relevanten Ausschnitt in 2.Sample kopieren und Saven:
If (EndPos-StartPos)>MinimumSampleGroesse
KlangFinish=CreateAudioSample((EndPos-StartPos)/4 , 44100 , SF_STEREO16LE)
For I=0 To (EndPos-StartPos)-1
KlangFinish.Samples[i] = Klang.Samples[i+StartPos]
Next
If AufnahmeAn=1
SaveOGG(KlangFinish,Pfad + SampleName +"\" + SampleName + Ton + ".ogg")
Else
Print "Simulate SaveOGG... " + Pfad + SampleName +"\" + SampleName + Ton + ".ogg"
EndIf
EndIf
End Function


Zum Quellcode:


Hier findet Ihr die noch benötigte GMSounds.lst: https://www.blitzforum.de/upload/file.php?id=10657

Wichtiger Hinweis:
Das Programm muss auch während der Entwicklung immer korrekt beendet werden ( CloseWindow oder ESC), das sonst sowoh das OpenAL, als auch das MIDI-Device geöffnet bleiben kann und es wegen der CallBacks zu Abstürzen des Rechners kommen wird!


Der Quellcode des Programm benötigt folgende Module:

BaH.RtMidi
axe.oggsaver
BaH.Volumes
MaxGUI.Drivers

Hiweise für alle die keine Lust haben die Module nachzuladen.
Die drei letzen Module könnten relativ einfach herausgenommen werden.

Der axe.oggsaver lässt sich auch durch die WAV-Save-Routine aus meinem AudioRecording-Tutorial ersetzen. Man muss nur eine Zeile auskommentieren und kommt dann ohne das Modul aus.

Die MaxGui dient nur der Bequemlichkeit. Ein Weg ohne MaxGui findet ihr weiter unten.

Bah.Volumes benötige ich nur einmal zum Finden des Verzeichnis "eigene Dateien". Man muss nur eine Zeile auskommentieren und kommt ohne das Modul aus.



Und hier das ganze ohne GUI:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Import BaH.RtMidi
Import axe.oggsaver ' *) kann weggelassen werden (siehe Projektseite bei blitzforum.de)

Graphics 300,200



' OpenAl-Ckeck und Start
If OpenALInstalled()=False Then
RuntimeError "Bitte OpenAL installieren!"
EndIf

EnableOpenALAudio()
SetAudioDriver("OpenAL")

Global Device%
Device=alcOpenDevice(Null)
If Device=Null Then
RuntimeError "Kein Zugriff auf Open-AL-Device möglich!"
EndIf

Global CaptureDevice%
If (alcIsExtensionPresent(Device, "ALC_EXT_CAPTURE") = AL_FALSE) Then
RuntimeError "Kein Recording möglich!"
EndIf

CaptureDevice = alcCaptureOpenDevice(Null, 44100, AL_FORMAT_STEREO16, 44100*2*2*6);
If Not(CaptureDevice) Then
RuntimeError "Kein Zugriff auf Open-AL-CAPTURE-Device möglich!"
EndIf

' Midi-Out-Check und Start
Global midiOut:TRtMidiOut = New TRtMidiOut.Create()
Global message:Byte[] = New Byte[3]


If midiOut.getPortCount() = 0 Then
Print "No Input Ports"
End
End If

For Local i:Int = 0 Until midiOut.getPortCount()
Print " Input port #" + i + " : " + midiOut.getPortName(i)
Next

Print "Opening " + midiOut.getPortName()
midiOut.openPort(0)



' Main-Recording Schleife:
Global Anzahl%, Summe%, HolZeit%, AufnahmeAn%=1 , Spuren%=2 , Aufloesung%=2
Global GesamtSpeicherPlatz%= 44100 * Spuren * Aufloesung% * 6 ' 6 sec max!
Global Klang:TAudioSample=CreateAudioSample(GesamtSpeicherPlatz , 44100 , SF_STEREO16LE)
Global StartTon%, Ton%, EndTon%, Kanal% , Laut% , Mode%=0 , Lang% ,Warte%=500, Instrument% , SampleName$



'*************** H I E R A L L E W I C H T I G E N E I N S T E L L U N G E N T R E F F E N :

StartTon=36 ' von c
EndTon = 72 ' bis c''
Kanal=1 ' Töne=1 , Drums=9
Laut=90 ' Midi Volume
Lang=2000 ' Tonlänge: 500msec ~ ca 1/4 Note bei Tempo 120
Instrument=0 ' GM Instrument-Nr
SampleName="Piano"





Global Zeit%=MilliSecs()+500
Delay 200
ProgrammChange()
Ton=StartTon


Repeat
If (HolZeit<MilliSecs()) And (AufnahmeAn=1)
HolZeit=MilliSecs() +500
Print "aufnahme läuft"
EndIf

If Zeit<MilliSecs()
Select Mode
Case 0
alcCaptureStart(CaptureDevice)
Delay 50
'play
SpielTon Ton, Laut, Kanal
Zeit=Zeit + Lang
Mode=1

Case 1
'stop
SpielTon Ton, 0, Kanal
Zeit=Zeit+ Warte
Mode=2
Case 2
'record
alcCaptureStop(CaptureDevice)
HoleAlleSamplesAb
Zeit=Zeit+ Warte
Ton=Ton +1
Mode=0
End Select
EndIf

' Grafiken zeichnen, etc...
DrawText "press esc to exit",100,100
Flip 0
Delay 15
If Ton>=EndTon Then Exit

Until KeyHit(Key_Escape)

SpielTon Ton, 0, Kanal
midiout.Free
alcCaptureStop(CaptureDevice)
alcCloseDevice(CaptureDevice)
alcCloseDevice(Device)
End



Function HoleAlleSamplesAb()
Local KlangFinish:TAudioSample
Local StartPos%, EndPos% , i%, j% , Sum% , Wo%
Cls
EraseSample()
alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 4, Varptr(Anzahl))
Print Anzahl + " Samples stehen bereit"
If (Anzahl*Spuren*Aufloesung) < GesamtSpeicherPlatz Then
alcCaptureSamples(CaptureDevice, Klang.Samples, Anzahl)
Print "Samples kopiert auf " + Summe
Summe=(Anzahl * Spuren* Aufloesung)
EndIf
For i=0 To GesamtSpeicherPlatz Step 200
Sum=0
For j=0 To 399 Step 4
Wo= i + j + 1
If Klang.samples[wo]<128 Then
sum=sum+Klang.samples[wo]
EndIf
Next
If sum>500
StartPos = i
Exit
EndIf
Next
EndPos=StartPos+200
For i = Int(GesamtSpeicherPlatz/400-1)*400 To 0 Step -200
sum=0
For j=0 To 399 Step 4
Wo= i + j + 1
If Klang.samples[wo]<128 Then
sum=sum+Klang.samples[wo]
EndIf
Next
If sum>250
EndPos = i+ 400
Exit
EndIf
Next
Print "Startpos " + startpos
Print "Endpos " + endpos
If (EndPos-StartPos)>4000
KlangFinish=CreateAudioSample((EndPos-StartPos)/4 , 44100 , SF_STEREO16LE)
For I=0 To (EndPos-StartPos)-1
KlangFinish.Samples[i] = Klang.Samples[i+StartPos]
Next
SaveOGG(KlangFinish,"AutoOggs/" + SampleName + Ton + ".ogg")
EndIf
End Function




Function EraseSample()
Local i%
Print "erase"
For I=0 To 44100*4*5-1
Klang.Samples[i]=0
Next
End Function






Function SpielTon (Ton%, Laut% , Kanal%)
message[0] = 144 + Kanal
message[1] = Ton
message[2] = Laut
midiout.putMessage(message, 3)
End Function




Function ProgrammChange()
message[0] = 192+Kanal
message[1] = Instrument
message[2] = 0
midiout.putMessage(message, 2)
End Function




Mein besonderer Dank geht an Brucey, dessen Module eine echte Bereicherung der Basic-Comunity sind und unbekannterweise an Andreas Rozek, von dem das OggSave-Modul stammt.
  • Zuletzt bearbeitet von Midimaster am Fr, Mai 03, 2013 1:09, insgesamt 2-mal bearbeitet
 

Macintosh

BeitragMo, Mai 30, 2011 13:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Doch, es gibt auf den mac irgend so einen QuickTime Music Synthesizer.

Midimaster

BeitragMo, Mai 30, 2011 14:03
Antworten mit Zitat
Benutzer-Profile anzeigen
naja, aber der kann nur sog. Standard-Midifiles abspielen und stellt dem Programmierer kein MIDI-Device zur Verfügung. Quicktime bereitet dann das ganze MIDI-File auf, läd irgendwo her die benötigten Sounds und startet mit 500msec Verzögerung das Abspielen. An seinen WaveTable kommt man leider nicht ran und die Performance wäre auch jenseits von gut und böse...

Eine MIDI-Device Schnittstelle benötigst Du aber, wenn Du einzelne Events an MIDI senden willst. Das Microsoft-GS-Wavetable stellt hier einen Zugang bereit, benötigt aber auch 160msec um jeden Event in Sound umzusetzen. Mit BlitzMax und Samples statt MIDI sind aber durchaus Latenzen von unter 40msec drin.

Also ist das ganze sogar eine Alternative für Windows-Coder, die normalerweise den Microsoft-GS-Wavetable nutzen. Zumal diese eigenen "Midi-Sound" von einem sehr hochwertigen MIDI-Keyboard kommen könnten und damit sogar das Roland Sound-Canvas alt aussehen lassen.

BladeRunner

Moderator

BeitragMo, Mai 30, 2011 15:01
Antworten mit Zitat
Benutzer-Profile anzeigen
Interessantes Stückerl Code, allerdings muss ich ein

~Wichtiger Hinweis~
In diesem Thema über juristische Angelegenheiten kann und wird keine verbindliche Rechtsberatung stattfinden.
Alle Antworten sind unverbindlich und geben lediglich die Meinung ihrer Autoren wieder.

hier einfügen, da ich mir nicht sicher bin ob es zulässig ist (ich bezweifle es arg) die Sounds von Synthesizern und Co zu Rippen. Zumindest wenn es um mehr als reine Privatnutzung geht.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Midimaster

BeitragMo, Mai 30, 2011 19:43
Antworten mit Zitat
Benutzer-Profile anzeigen
ich hab da mal recherchiert....


Die WaveTables zu kopieren wäre nicht zulässig. Sie sind aber auch etwas ganz anderes als eine Aufnahme von ihnen. Sie wesentlich mehrdimensionaler als der eine Sample einer Aufnahme.

Bei der Aktion mit dem GS-TO-OGG-Konverter findet eine reine Aufnahme statt. Die anschließenden Ogg-Files entsprechen nicht mehr dem Ausgangsmaterial. Ähnlich der Verwendung der Fonts via TImagefont.

Die Aufnahme eines Instrumentes ist keine Lizenzverletzung gegen den Instrumentenhersteller. Er hat ein Recht am Instrument, jedoch nicht am Klang, den ich damit erzeuge. Der Ton als solcher ist nicht schützenswert (siehe unten). Zwar dürfte ich auch markenrechtlichen Gründen nicht damit werben, den "Steinway" kopiert zu haben. Da aber alle aufgenommen Töne durch meiner Hände Arbeit erklingen, sind sie wenn überhaupt, dann "mein" Werk.



Hier einige bei der Aufnahme verlorengegangene Merkmale:

1. Hüllkurve weg

Samples sind nur Momentaufnahmen des Ausgangsmaterial mit einer fixen Länge. Dabei geht zumindest das Verhalten der S und R Anteile der Hüllkurve verloren (ADSR= Attack Decay Sustain Release). Die Flexibiliät, die der Original-Wavetable hierzu bieten konnte, bleibt auf der Strecke.

2. Dynamik weg

Die Samples sind auch nur eine Momentaufnahme fester Lautstärke. Hier geht vor allem das Dynamikverhalten des Ausgangsmaterials verloren (Brightness). D.h. das leise abgespielte Sample wird nachher nicht wie ein leises Klavier klingen, sondern wie ein leisen Abspielen eines lauten Klaviers.

3. Interaktion unmöglich

Im Sample finden keine Interaktion zwischen den Tönen mehr statt, wie sie im Instument üblich sind. Etwa endet bei den Sample-Drums die OpenHihat nicht durch das Erscheinen einer ClosedHihat. Oder die geniale Verzerrung einer Clavia Nord Elektro Hammond-Orgel, die nur auftritt, wenn ich best. Intervalle spiele, kann ich nicht mitsamplen....

hierzu einige Links:

http://www.it-recht-kanzlei.de/Download|Rechtsthemen|Urheberrecht|20060802_Urheberrechtliche_Einordnung_der_aktuellen_Madonna-Single,_die_sich_Samples_der_Kultband_Abba_bedient.txt.html


aus http://wiki.myownmusic.de/inde...heberrecht :
Zitat:
Frage: Wenn ich einen einzelnen Ton sample, z.B. Geigenstreicher und mir dann aus diesem Ton eine eigene Melodie bastele, ist das erlaubt?
Antwort: Ein-Ton-Samples sind nicht schützenswert, es ist also erlaubt, aber man könnte es dann genauso gut selber einspielen.
Hinweis: Das war genau die strittige Frage, ehe das neue Urheberrechtsgesetz in Kraft trat. Es ging darum, daß einige Hersteller elektronischer Instrumente ein Schutzrecht für ihre besonderen Soundsamples reklamierten. Wohlgemerkt - nur die Sounds der einzelnen Tasten oder Patches. Dies wäre natürlich in der Praxis und auch technisch nicht umsetzbar und entbehrt auch jeder rechtlichen Grundlage.

Midimaster

BeitragFr, Mai 03, 2013 1:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe ein Update des Konverters reingestellt und den ersten Post (siehe oben) aktualisiert.

verbesserte Features:

- Midi Volumen als einstellbaren Wert hinzugefügt
- Front Cut ThresHold schneidet die Stille vor der Aufnahme raus
- Back Cut ThresHold schneidet am Ende der Aufnahme zu Leises raus
- einige Fehler ausgebessert
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group