Audio Input mit Datei abgleichen

Jeff500

Mitglied
Hallo Community,

Ich hab ein Problem dabei einen AudioInputStream auf einen Ton hin zu durchsuchen.

Ich habe eine Audiodatei, die etwa 70 Millisekunden dauert und nur einen Ton beinhält. Diese Wandel ich in einen Byte-Array (1) um. Dann nehm ich ständig etwa 5 Sekunden vom Mikrofon-eingang auf, wandel es in einen Byte-Array (2) um und gleich es mit (1) ab und zwar byte für byte.

Quelltext:

Java:
public boolean abtasten(byte[] s)           //Byte-Array des zu durchsuchenden Aufgenommem
    {
        
        byte[] searchingTone = archive.searchToneGeben();         //Byte-Array des zu Suchenden Tons
        
//Beginn der Abgleich-Schleife

        for(int i = 0; i < s.length - searchingLength; i++) 
        {
            
            int match = 0;
            
            for(int k = 0; k < searchingToneLength; k ++)
            {
                
                if(s[i+k] == searchingTone[k])
                {
                    match ++;
                }
            }
//Ende der AbgleichSchleife

            double m = ( (double)match / (double)searchingToneLength ) * 100;
            
            //wenn die Übereinstimmung größer als 60% ist wird noch nach mehr gesucht, für mein Problem aber unwichtig

            if( m > 60)                          
            {
                if(abtastenGenau(s))
                {
                    return true;
                }
            }
        }
        return false;
    }

selbst wenn ich genau den ton in dauerschleife anleg, wird m, also die Übereinstimmung nicht größer als 3, obwohl es meiner überlegung nach 100 sein sollte

Ich bin sicher, dass sowohl Array (1), als auch (2) mit daten gefüllt sind.

Meine Vermutung ist, dass man 2 durch die methode AudioInputStream.read(byte[]) gefüllte Arrays nicht so ohne weiteres vergleichen kann, weiß aber nicht genau wie ich das Problem anders lösen könnte.
Falls es wichtig ist die beiden Arrays sind von AudioStreams mit einer SampleRate von 11025 Herz, einer SampleSizeInBits 8, 2 channels, FrameSize 2 und FrameRate 11025 gefüllt worden.

Vielen Dank im Vorraus und viele Grüße,
Jonas
 
lass dir die arrays doch einfach mal mit nem loop und Integer.toHexString(int) ausgeben ... dann siehst du ob auch wirklich die selben daten drin sind ...
 
Nachdem ich mir heute mal die Arrays ausgeben hab lassen, bin ich zu dem Schluss gekommen, dass sich mein Problem (vergleichen von Audio) nicht auf meine Weise lösen lässt.
Mir fehlt zwar das Fachwissen dafür und es wäre extrem hilfreich, wenn jemand einen Crashkurs in Sachen Wavedateien-bytecode analysieren geben könnte, aber ich vermute, dass ich einen Ton (beispielsweise 2000Herz) erkennen kann, wenn ich die zwei Stellen in seinem Bytecode vergleiche, an denen der Sinus den gleichen Wert hat.

Beispiel:
2000Herz = 2000 Schwingungen/Sekunde(s) = 2 Schwingungen/ms
SampleRate von 11025Hz = 11 Samples pro Sekunde
=> 1 Schwingung wird in 5,5 Samples aufgeteilt, da SampleSizeInBits 8 ist, ist eine Schwingung mit 5,5 byte, also 5,5 Feldern im Array beschrieben. Das heißt es werden 2 Schwingungen mit 11 Byte beschrieben
=> da Stereo Sound, muss 11 * 2 genommen werden
=> jede 22. Stelle im Bytearray eines 2000Hz Tons, der mit 11025Hz aufgenommen (oder erzeugt) und bei dem ein Sample mit 8bit = 1 Byte beschrieben wird, ist (nahezu) identisch, da die Schwingung an der selben Höhe ist.

Diese Theorie hat sich anhand einer Aufnahme bewahrheitet. Übereinstimmung nicht ganz 100%, da nicht 11000Hz sondern 11025Hz.

Kann diese Überlegung stimmen, oder hat jemand eine bessere Idee, wie man eine Aufnahme nach einem Ton untersuchen kann?

PS: Wenn ich eine Audiodatei, die 10ms dauert und einen 2000Hz Ton spielt als byteArray ausgeben lasse, dann bekomm ich:
-128-128-128-128-128-128-128-128-128-128
kann das irgendjemand erklären, oder wird jemand daraus schlau?

Wenn ich eine datei, mit dem selben Ton selbe Auflösung und ansonsten auch alles gleich, nur dass diese 70ms dauert ausgeben lässt, ergibt die Ausgabe einen gewissen Sinn und meine oben genannte Theorie kann auch angewendet werden, kurz man kann eine Sinuskurve hineininterpretieren. Aber der Array, in dem einfach nur 10 mal die selbe zahl ist, ergibt für mich keinen sinn.

@irgendjemand
Danke für die schnelle antwort, aber meine Überlegung mit dem byteweisen abgleich ist, vermutlich wenig sinnvoll und muss nicht weitergeführt werden.
 
hmm ... da ich mich auch mit "visueller mustererkennung" beschäftigt habe *oder kurz : captcha-cracking* weis ich das man jede information natürlich als eine abfolge bestimmter byte-sequenzen abbilden kann ...
auch wenn es bei der visuellen mustererkennung methoden gibt mit denen man das stark vereinfachen kann *z.b. Hough-transformation* bin ich mir sicher das es sowas auch für audio geben muss ...

vielleicht wäre noch ein ansatz zu versuchen das audio-signal zu visualisieren ... also die schwingungen graphish darzustellen ... und dann darauf mit hough-tansform *ist ganz einfach ... meine beste impl waren mal um die 800 zeilen* anzuwenden ...

ja ... ich höhre schon die schreie wie umständlich das ist ... aber es wäre EINE möglichkeit ... effizienter wäre es natürlich ohne diesen umweg ... aber da kenne ich mich dann doch nicht so gut aus
 
hmm ... da ich mich auch mit "visueller mustererkennung" beschäftigt habe *oder kurz : captcha-cracking* weis ich das man jede information natürlich als eine abfolge bestimmter byte-sequenzen abbilden kann ...
Aber man muss sich nicht mit visueller Mustererkennung auseinandersetzen, um zu erfahren, dass eigentlich jede Datei, jeder Speicherbereich und was weis ich noch was schlicht Bytesequenzen sind, die irgend etwas abbilden. Etwas anderes versteht so ein Rechner nun mal nicht.
Da ich nicht genau weis, was der TO vorhat, wende ich jetzt bei Ihm meine Mustererkennung an und frage mal ganz frech... soll das 'ne Sprach-Steuerung werden? Wenn ja, dann ist dein Ansatz auf jeden Fall komplett falsch.
Ansonsten ist das nämlich gar nicht so verkehrt. Die Bytearrays zweier 2kHz-Schwingungen mit annähernd gleicher Amplitude die an exakt der selben Stelle beginnen, sollten inhaltlich gleich sein. Exakt an der selben Stelle ist das Schlagwort. Beginnen sie an verschiedenen Stellen im Sinus wird eine Triggerung oder eine stete Verschiebung des Vergleichsignals erforderlich, für Sprachsteuerung aber ist das nicht zu gebrauchen. Bei einfachen Frequenzen ist's noch relativ einfach, bei Musik (Klängen) wird's schon schwieriger und bei Sprache... OMG. Wenn ich nur an DFT (discrete Fourier Tranformation) denke, wird mir schlecht.
Aber da bist du noch lange nicht. Dir fehlen ja noch Grundlagen... zumindest die eine, das 8-Bit-Stereo-Bytearrays den Aufbau RLRL... haben, die Wellenform für einen Kanal also in jedem 2. Byte steckt.
Als nächstes würde ich im übrigen auch zu Fliesskomma-Arithmetik wechseln, statt bei Integern zu bleiben, dann kann man nämlich die Amplituden unabhängig von ihrem Wert erkennen. Wenn mann nämlich zwei gleiche in Phase liegende Frequenzen unterschiedlicher Amplituden von einander abzieht, resultiert daraus ein Amplitudenverlauf gleich dem der beiden Frequenzen, nur halt mit kleineren bzw. grösseren Beträgen. Bei gleichen Amplituden resultiert logischerweise eine 0-Linie.
 
1.Danke für eure Hilfe


2.
frage mal ganz frech... soll das 'ne Sprach-Steuerung werden?
Absolut nicht, so was kompliziertes würde ich nich mit so nem Logarithmus anfangen. Es geht darum, dass die Feuerwehr über piepser alarmiert wird, genauer, wenn eine bestimmte Tonfolge gesendet wird 5-Ton-Folge ? Wikipedia, dann läuft ein programm an, was des macht is nicht wichtig, darum kümmer ich mich dann schon 😉
Meistens sind des drei verschiedene Töne, von daher hab ich mir überlegt, dass meine SampleRate so gewählt werden muss, dass man sie durch alle Frequenzen der Töne ohne Rest teilen kann ...

3.
jede information natürlich als eine abfolge bestimmter byte-sequenzen abbilden kann ...
soweit war ich schon, aber da ich nicht weiß, wie ich aus einer bytefolge ganz elementare Informationen auslesen kann (manuell nicht über ein programm), alles was ich bis jetzt weiß, ist dass immer zwei bytes direkt hintereinander für die beiden kanäle (stereo) stehen, und viele verschiedene zahlen andeuten, dass ein signal ankommt :toll:
Wenn ich da etwas hilfe bekäme, dann könnte ich mir evtl selber nochmal wege ausdenken, wie das programm regelmäßigkeiten oder bestimmte folgen im bytecode suchen kann.

4.
vielleicht wäre noch ein ansatz zu versuchen das audio-signal zu visualisieren ... also die schwingungen graphish darzustellen ... und dann darauf mit hough-tansform *ist ganz einfach ... meine beste impl waren mal um die 800 zeilen* anzuwenden ...
Wie du schon erwähnt hast, is des anscheinend sehr aufwändig, und da die Abtastung annähernd in echtzeit ablaufen muss, und ständig neuer Input verarbeitet werden muss, is des vermutlich nicht zu realisieren.

5.
klingt als ob Diskrete Fourier-Transformation gesucht wird.
OK, da bin ich momentan überfordert, kurze info, was genau das ist oder wie des arbeitet, bzw versteh ich des, wenn ich noch nicht mitm abi fertig bin 😱 ?

6.
Die Bytearrays zweier 2kHz-Schwingungen
Nachdem ich jetzt erkannt hab, dass direktes vergleichen von zwei für den Menschen ähnlicher Inputs(e?) für den computer wenig sinnvoll ist, war die neue überlegung aus meinem letzten post, dass ich nur den mikrofon input, auf einen bestimmten Ton mit evtl bestimmter länge untersuchen (signal ist ja simpel aufgebaut), oder ist die methode mit der Triggerung einfacher umzusetzen ?

7.
Wenn mann nämlich zwei gleiche in Phase liegende Frequenzen unterschiedlicher Amplituden von einander abzieht, resultiert daraus ein Amplitudenverlauf gleich dem der beiden Frequenzen, nur halt mit kleineren bzw. grösseren Beträgen. Bei gleichen Amplituden resultiert logischerweise eine 0-Linie.
Das funktioniert doch wieder nur, wenn beide aufnahmen so starten, dass maxima und minima zur selben zeit sind, oder ? Wenn ja, dann kommt das nicht in Frage, da permanent Ausschnitte aufgenommen werden und das gesuchte Signal irgendwann dabei ist.
 
Zuletzt bearbeitet:
Oi... da kommt mir ja ein zunächst recht simpler Gedanke, sofern das Signal auch definitiv 2 Mal gesendet wird. Du startest mit einer Schwellwert-Triggerung und nimmst dann 400ms auf, machst 550ms Pause und nimmst nochmal 400ms auf. Die beiden entstehenden Frequenzverläufe sollten in etwa kongruent sein, das bekommst du über einen Kovolutions-Algo heraus, welchen du dir hier mit möglicherweise aus dem Applet des ersten Links als Java-Implementation besorgen kannst.
[EDIT]
es sind natürlich 11,025 (wird gerundet auf 11) Samples pro Millisekunde
Mit anderen Worten 770 (Stereo?) Samples pro Ton oder 3850 pro Tonfolge? Lass' die 0,025 um himmels Willen nicht ausser Acht. Du würdest dich Wundern.[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:
ich komm auf 771,75 Samples pro Ton 😉 ja die rechnugnen sind nur überschlagen, ob das system funktionieren könnte

schwellwert- triggerung ? tud mir leid, aber meine java kenntnisse beschränken sich auf schulinformatik und was ich mir über tutorials noch beigebracht hab 🙁

Die beiden entstehenden Frequenzverläufe sollten in etwa kongruent sein
meinst du damit, dass ich einfach nur schau, ob 2x das selbe reinkommt und gar nicht analysier, welche töne das sind ?
 
meinst du damit, dass ich einfach nur schau, ob 2x das selbe reinkommt und gar nicht analysier, welche töne das sind ?
Öhm... ja. Okay, Sch... Idee, obwohl die mit gespeicherten Tonfolgen auch funktionieren müsste.
Eine Schwellwert-Triggerung startet z.B. eine Aufnahme, sobald ein gewisser Geräuschpegel erreicht ist. Nutzt du zufällig TeamSpeak oder ähnliches? Dann weisst du sicher, dass man dort das Mikro auch über Sprache aktivieren kann und welche Einstellungen dazu nötig sind. Das ist eine Schwellwert-Triggerung. Hat nichts mit Informatik zu tun. 😉
 
Zuletzt bearbeitet von einem Moderator:
OK ich bastel nochmal bisl an meiner neuen Idee rum und dem schon genannten und stell dann entweder die Lösung hier rein oder komm wieder mit genaueren fragen
 

Zurück
Oben