MakeSound - eine Alternative zu Beep Melodien, mit Dateiausgabe

  • Hi Leuz,
    ich hab mich mal eine Weile mit Ton Generierung beschäftigt und mit dem Problem das die Beep() einfach nicht zum Melodien ausgeben gemacht ist. Daraus entstanden ist eine einfache UDF mit der BASS DLL. Diese ermöglicht das die Melodie auch in eine WAV gespeichert werden kann. Zum Ton generieren nutze ich Assembler.

    Ein Dank geht an:
    eukalyptus für seine BASS UDF
    Ward für die inline FASM UDF

    Hier noch ein kurzes Beispiel und noch viel Spaß damit :). Feedback ist natürlich immer erwünscht ;)

    Beispiel (Tonleiter)
    [autoit]

    #AutoIt3Wrapper_UseX64=n
    #include "MakeSound.au3"
    #include <Sound.au3>
    ;by Sprenger120

    [/autoit] [autoit][/autoit] [autoit]

    _MakeSound_Startup() ;startup MakeSound

    [/autoit] [autoit][/autoit] [autoit]

    $aWAV = _MakeSound_CreateWAV(@ScriptDir & "\record.wav",10000) ;Creats a MakeSound WAV

    [/autoit] [autoit][/autoit] [autoit]

    For $iFreq = 50 To 10000 Step 50
    _MakeSound_InsertSound($aWAV,$iFreq, 200) ;Insert Tones
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _MakeSound_Write($aWAV) ;Save it to a file
    _MakeSound_Shutdown() ; shutdown MakeSound

    [/autoit] [autoit][/autoit] [autoit]

    ;play sound
    $hSound = _SoundOpen(@ScriptDir & "\record.wav")
    _SoundPlay($hSound)
    While Sleep(100)
    if _SoundPos($hSound,2) >= _SoundLength($hSound,2) Then ExitLoop
    WEnd
    _SoundClose($hSound)

    [/autoit]
    ToDo

    -BASS durch direktes WAV schreiben ersetzen
    -übergänge zwischen den Tönen berechen (letzte Schwingung abtrennen)
    -Stereo Generierung ermöglichen
    -Sägezahn Töne
    -Rechteck Töne
    -Erst bei Null anfangen zu schreiben
    -Pi als Double in die Berechnung mit einbeziehen

  • Sehr cool! :thumbup:

    2 Verbesseungsvorschläge:
    .) Du könntest auf BassEnc verzichten und die Wav selber herstellen. Wie das geht siehst du in BassExt.au3 bei der Funktion _BASS_EXT_SpVoice2Memory und dessen Beispielscript. Das Resultat kannst du direkt aus dem Speicher abspielen und/oder binär als Wav speichern.

    .) Crossfades zwischen den Tönen berechnen. Vielleicht genügt es auch schon, wenn du immer die letzte Schwingung beim Nulldurchgang stoppst.

    Und wenn du Lust hast noch Rechteck, Dreieck, Sägezahn usw -Wellen ^^ ...

    E

  • .) Du könntest auf BassEnc verzichten und die Wav selber herstellen. Wie das geht siehst du in BassExt.au3 bei der Funktion _BASS_EXT_SpVoice2Memory und dessen Beispielscript. Das Resultat kannst du direkt aus dem Speicher abspielen und/oder binär als Wav speichern.


    Jo, es geht aber auch ohne BassEXT. Man kann die Wave auch so Binär zusammensetzen, das ist nicht weiter schwer.

    .) Crossfades zwischen den Tönen berechnen. Vielleicht genügt es auch schon, wenn du immer die letzte Schwingung beim Nulldurchgang stoppst.


    Wird gemacht Chef :D

  • tolle udf ;D

    ich ich habe noch eine Funktion geschrieben, mit der man Noten (c, d,e usw..) in Frequenzen umrechnen kann (falls es das noch nicht gibt).

    Spoiler anzeigen
    [autoit]

    ; Note2Freq by Developer30
    Global $kammerton = 440
    Global $faktor = 2^(1/12) ; 12. Wurzel von 2
    Global $notes[12] = ["c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b"]

    [/autoit] [autoit][/autoit] [autoit]

    Func _Note2Freq($note, $oktave)
    $step=""
    if $step="" Then
    for $x = 0 to 11
    if $note=$notes[$x] Then $step = $x-9
    Next
    EndIf
    $oktStep = $oktave-4
    if $step > 0 then $NewFreq=$kammerton*($faktor^$step)
    if $step < 0 then $NewFreq=$kammerton/($faktor^($step*-1))
    if $step = 0 then $NewFreq=$kammerton
    if $oktStep > 0 Then $NewFreq=$NewFreq*($oktStep*2)
    if $oktStep < 0 Then $NewFreq=$NewFreq/($oktStep*-2)
    Return $NewFreq
    EndFunc

    [/autoit]


    im MusicalScale example könnte das dann z.B. so aussehen:

    Spoiler anzeigen
    [autoit]

    For $i= 0 To 11
    _MakeSound_InsertSound($aWAV,_Note2Freq($notes[$i], 4), 500) ;Insert Tones
    Next

    [/autoit]


    Edit: Funktion verbessert (danke @ eukalyptus für den Hinweis)

    "Je mehr Käse, desto mehr Löcher; je mehr Löcher, desto weniger Käse. Ergo: Je mehr Käse, desto weniger Käse. 8| "
    "Programmers never die: they just GOSUB without RETURN"
    "I tried to change the world but I couldn't find the source code."

    2 Mal editiert, zuletzt von Developer30 (9. April 2011 um 00:05)

  • Zitat

    Schöne Umsetzung! Du bist ja ein klein Andy!

    Was heisst kleiner? Ich muss ganz schön Gas geben, die Jungs werden immer besser! Aber genau das freut mich ja, da machts doppelt und dreifach Spass!

    Sprenger120, ganz klasse Arbeit! :thumbup:

  • kann es sein, dass da beim Tongenerator was nicht stimmt?
    wenn ich einen 440Hz Ton mit der UDF generiere, dann ist der einen halben Ton zu tief. Ich habe zum Vergleich mal mit Audacity einen 440Hz Ton generiert (siehe Anhang: 1. Ton aus der UDF; 2. Ton aus Audacity).

    Spoiler anzeigen
    [autoit]

    #AutoIt3Wrapper_UseX64=n
    #include "MakeSound.au3"
    #include <Sound.au3>

    [/autoit] [autoit][/autoit] [autoit]

    ;by Sprenger120

    [/autoit] [autoit][/autoit] [autoit]

    _MakeSound_Startup() ;startup MakeSound
    $aWAV = _MakeSound_CreateWAV(@ScriptDir & "\record.wav",10000) ;Creats a MakeSound WAV
    _MakeSound_InsertSound($aWAV,440, 500) ;Insert Tones
    _MakeSound_Write($aWAV) ;Save it to a file
    _MakeSound_Shutdown() ; shutdown MakeSound

    [/autoit]

    Dateien

    "Je mehr Käse, desto mehr Löcher; je mehr Löcher, desto weniger Käse. Ergo: Je mehr Käse, desto weniger Käse. 8| "
    "Programmers never die: they just GOSUB without RETURN"
    "I tried to change the world but I couldn't find the source code."

  • Hi,
    hm ja SoundMake generiert tiefere Töne. Das könnte folgenden Grund haben: Bei SoundMake wird immer der Wert der von FSIN ausgegeben wird *32767 gerechnet und das könnte die Kurve irgentwie beeinflussen.
    Dieses Bogensehnengeräusch vom Anfang könnte daher kommen das MakeSound einfach mitten in der Sinus Kurve anfängt und nicht im 0 Punkt.


    Hier mal ein kleiner Vergleich
    Soundmake: autoit.de/wcf/attachment/13058/ Audacity: autoit.de/wcf/attachment/13059/


    Hab mal auf die ToDo gesetzt das er immer erst bei Null anfangen soll Sounddaten zu schreiben.

  • ja, ich denke das hängt damit zusammen.

    Ich habe mal die Wellenlänge aus dem Makesound-Beep kopiert (Bild 2), und bei dem Audacity-Beep eingefügt (roter Strich in Bild 1).
    Wie man sieht, ist der rote Strich länger als der blaue, würde heißen, dass die Wellenlänge nicht stimmt. Soweit ich weiß, ist die Tonhöhe ja von der Wellenlänge anhängig.

  • Sorry, mein Fehler hab ausversehen auf der Tastatur herumgetippt,und herausgekommen ist in
    Jetzt gehts perfekt, hab mir alles neu runtergeladen ;)