Guten Abend miteinander
folgendes: Ich baue ein Messgerät mit einem Raspberry Pi. Am Raspberry Pi ist ein Piezosensor angeschlossen welcher an einem Objekt befestigt wird. Nun mache ich eine Tonaufnahme (arecord) und erstelle daraus ein wave-File. Als nächstes muss ich prüfen, ob überhaupt etwas "spannendes" aufgenommen wurde. Dazu soll überprüft werden, ob ein gewisser Amplituden-Wert überschritten wird. Falls nein, kann die Aufnahme wieder gelöscht werden. Falls der Wert erreicht wird sollen Alle Werte die diesen Wert überschritten haben mit ihrem "Timestamp"/Index in eine Datei gepeichert werden. Also so ala:
Sekunden | Wert
1.2 | 0.2
1.3 | 0.5
(Diese Datei muss nachher über eine langsame Netzwerkverbindung mit Datenlimit verschickt werden und somit sollen "uninteressante" Messungen gar nicht verschickt werden)
Ich bin aktuell so vorgegangen, dass ich mit arecord eine .wav erstellt habe und sie nachher über "sox" in eine .dat Datei umgewandelt habe. Nun soll diese .dat eingelesen werden und in einer Schleife eine Grenzwert geprüft werden.
Problem ist jetzt, dass dieses .dat mit open(datei.dat) als String eingelesen wird, mit ganz vielen Leerschlägen und ";" usw.
Beispiel (eben mit ganz vielen Leerschlägen vor und nach den Zahlen:
0.0013605442 0.00012207031
0.0014058957 0.00015258789
0.0014512472 0
0.0014965986 6.1035156e-05
0.0015419501 0.00021362305
Wie kann ich diese Strings nun in ein sinnvolles Zahlenformat formatieren, damit ich dann Grenzwerte prüfen kann?
Ich hoffe jemand versteht was ich gerne möchte und kann mir helfen.
Lieber Gruss
Tonaufnahme einlesen und Komprimieren
Hallo
vielen Dank für die Antworten.
Ich habe mich jetzt mal mit dem pyaudio befasst.
Wenn ich jetzt 1 Senkunde aufnehme, dann ergibt die Rechnung t2-t1 ca 1.6-2.3 Sekunden!
Wenn ich jetzt 20 Sekunden aufnehme, dann ergibt die Rechnung t2-t1 ca. 33 Sekunden... Warum ist das so?
Danke für eure Hilfe und Gruss
vielen Dank für die Antworten.
Ich habe mich jetzt mal mit dem pyaudio befasst.
Code: Alles auswählen
Testrecording_Dauer = int(Rate / Chunk)*Dauer
t1=time.time()
for i in range(0, Testrecording_Dauer): #Eine Sekunde aufnehmen und Schauen was abgeht...
data = stream.read(CHUNK, exception_on_overflow = False)
aframe = np.asarray(data)
npframes = np.vstack((npframes,aframe))
t2=time.time()
print ("finished testrecording. Dauer: ", t2-t1)
Wenn ich jetzt 20 Sekunden aufnehme, dann ergibt die Rechnung t2-t1 ca. 33 Sekunden... Warum ist das so?
Danke für eure Hilfe und Gruss
Also die Werte aus einem Numpy-Array, die einen bestimmten Wert überschreiten, kriegt man so:yakari9 hat geschrieben:Als nächstes muss ich prüfen, ob überhaupt etwas "spannendes" aufgenommen wurde. Dazu soll überprüft werden, ob ein gewisser Amplituden-Wert überschritten wird. Falls nein, kann die Aufnahme wieder gelöscht werden.
Code: Alles auswählen
# 10 Zufallswerte als Beispiel
values = np.random.rand(10)
print(values)
print(values[values >= 0.5])
Also, natürlich ist das CHUNK immer gleich geschrieben. Ich habe hier mal den ganzen Code eingefügt.
Es wird folgendes gemacht:
1. Importieren von Modulen
2. Variablen definieren
3. Jetzt kommt eine While Schleife, mit dieser soll eine kontinuierliche Ausführung des Programmes möglich sein
a) Testrecording starten (Kurze Aufnahme die prüft, ob ein Geräusch auftritt = Grenzwert überschritten wird)
Falls nicht, beginnt die while Schleife wieder von vorne...
b) sobald "Lärm" detektiert wird (= Grenzwert überschritten) kommt, startet die eigentliche Messung (hier Dauer 10Sekunden siehe Variable Messdauer). DIese funktioniert wiefolgt:
i.) wieder Aufnehmen wie punkt 3.a
ii.) Gerenzwert prüfen wie von "snafu" vorgeschlagen
iii.) Gefundene Überschreitungen mit Ihren Indizes in ein Array schreiben und abspeichern
iv.) je nach Wert der Variable "go" wird jetzt der Prozess wieder bei Punkt 3.a gestartet oder beendet
4. Wird der Prozess beendet, wird noch die Mess-Aufnahme als .wav gespeichert. Damit soll überprüft werden können ob das Programm funktioniert
Das ganze umwandeln, überprüfen, abspeichern und kopieren geht keine Sekunde! Die Aufnahme ist jedoch einfach immer langsamer als sie sollte. Die Dauer eines Testrecordings (welche 1s sein sollte) ist 1.6-2.3s
Die Dauer eines Messdurchgangs (welche 16s sein sollte) ist 16s
Komischerweise scheint der Faktor 1.6 irgendwie mitzuspielen. Die erstellte .wav Datei ist aber nicht um diesen Faktor verlängert!
Was meint ihr?
Code:
Es wird folgendes gemacht:
1. Importieren von Modulen
2. Variablen definieren
3. Jetzt kommt eine While Schleife, mit dieser soll eine kontinuierliche Ausführung des Programmes möglich sein
a) Testrecording starten (Kurze Aufnahme die prüft, ob ein Geräusch auftritt = Grenzwert überschritten wird)
Falls nicht, beginnt die while Schleife wieder von vorne...
b) sobald "Lärm" detektiert wird (= Grenzwert überschritten) kommt, startet die eigentliche Messung (hier Dauer 10Sekunden siehe Variable Messdauer). DIese funktioniert wiefolgt:
i.) wieder Aufnehmen wie punkt 3.a
ii.) Gerenzwert prüfen wie von "snafu" vorgeschlagen
iii.) Gefundene Überschreitungen mit Ihren Indizes in ein Array schreiben und abspeichern
iv.) je nach Wert der Variable "go" wird jetzt der Prozess wieder bei Punkt 3.a gestartet oder beendet
4. Wird der Prozess beendet, wird noch die Mess-Aufnahme als .wav gespeichert. Damit soll überprüft werden können ob das Programm funktioniert
Das ganze umwandeln, überprüfen, abspeichern und kopieren geht keine Sekunde! Die Aufnahme ist jedoch einfach immer langsamer als sie sollte. Die Dauer eines Testrecordings (welche 1s sein sollte) ist 1.6-2.3s
Die Dauer eines Messdurchgangs (welche 16s sein sollte) ist 16s
Komischerweise scheint der Faktor 1.6 irgendwie mitzuspielen. Die erstellte .wav Datei ist aber nicht um diesen Faktor verlängert!
Was meint ihr?
Code:
Code: Alles auswählen
import pyaudio
import wave
import time
import sys
import numpy as np
import utility
from shutil import copyfile
### Aufnahmevariablen ###
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 1024
RECORD_SECONDS = 1
WAVE_OUTPUT_FILENAME = "record.wav"
go=0
audio = pyaudio.PyAudio()
###-----###
### stream definieren ###
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True, input_device_index=2,
frames_per_buffer=CHUNK)
###-----###
##### Messvariablen ###########
Grenzwert=0.002
Testrecording_Dauer = 1 #Sekunden
Messdauer = 10 #Sekunden
###-----###
while go<2:
### Testrecording ###
npframes=np.array([0]) # np.Array für die Aufnahme generieren
print("Testrecording...")
t1=time.time()
for i in range(0, int(RATE / CHUNK * Testrecording_Dauer)): #Eine Sekunde aufnehmen und Schauen was abgeht...
data = stream.read(CHUNK, exception_on_overflow = False)
#frames.append(data)
aframe = np.asarray(data)
npframes = np.vstack((npframes,aframe))
t2=time.time()
print ("finished testrecording. Dauer: ", t2-t1)
### Daten umwandeln ###
sig = np.frombuffer(npframes, dtype='<i2').reshape(-1, CHANNELS) #Das Signal wird konvertiert
normalized = utility.pcm2float(sig, np.float32) #und normalisiert
### Überprüfen ob der Grenzwert überschritten wurde ###
for i in range(0, len(normalized)):
if normalized[i] > Grenzwert:
go = 1 #Falls ja(go=1), wird das Flag go=1 gesetzt und die Schleife abgebrochen
break
### Messung - Wird gestartet wenn ein Geräusch detektiert wurde ###
if go == 1: #Falls go=1 dann soll eine lange Messung durchgeführt werden. Falls nicht werden die Testmessungen weitergeführt
print("Messung starten")
go=0 #Zurücksetzen des Go-Flags = nach dem Messdurchgang wieder mit Testrecording beginnen
t1=time.time()
frames=[]
for i in range(0, int(RATE / CHUNK * Messdauer)): #Messdauer Sekunden lang messen
data = stream.read(CHUNK, exception_on_overflow = False)
aframe = np.asarray(data)
npframes = np.vstack((npframes,aframe))
t2=time.time()
print ("finished recording. Dauer: ", t2-t1)
frameswav=npframes #Variable für das Abspeichern der wav-Datei
### Daten umwanden ###
sig = np.frombuffer(npframes, dtype='<i2').reshape(-1, CHANNELS)
normalized = utility.pcm2float(sig, np.float32)
go=2 # go=2 Messung nur einmal durchführen und anschliessend Programm beenden
t8=time.time()
### Grenzwerte prüfen ###
overgrenzwert=normalized[normalized >= Grenzwert] # Array mit allen Werten über dem Grenzwert
overgrenzwert = np.transpose(overgrenzwert)
indexes=np.nonzero(normalized >= Grenzwert) # Indexes der Werten über dem Grenzwert
indexes = np.transpose(indexes)
indexes = np.delete(indexes, 1,1)
compressed = np.stack((indexes,overgrenzwert[:, None]),axis=1) # Zusammenführen der Arrays
### Datei speichern
np.savetxt('compressed.dat',compressed,delimiter=';') #Speichern der Datei "Compressed.dat"
copyfile('compressed.dat', '/home/shares/test/compressed.dat') # Kopieren in Share-Ordner
print("Das hat gedauert, und zwar: ", time.time()-t1," Sekunden")
#stop Recording
stream.stop_stream()
stream.close()
audio.terminate()
### Wave Datei zur Überprüfung speichern
waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
frameswav.tolist()
waveFile.writeframes(b''.join(frameswav))
waveFile.close()
copyfile(WAVE_OUTPUT_FILENAME, "/home/shares/test/wavaufnahme.wav")
Wozu brauchst du eigentlich vstack()? Falls du die Frames hintereinander weg schreiben willst, dann ist dafür hstack() gut geeignet:
Aber grundsätzlich würde ich die Daten überhaupt nicht gesammelt speichern, sondern sofort verarbeiten.
Hier mal grob als Generator umgesetzt:
Oder gleich mit dem passenden Python-Builtin:
Code: Alles auswählen
data = np.hstack(
stream.read(chunk_size) for _ in range(num_chunks)
)
Hier mal grob als Generator umgesetzt:
Code: Alles auswählen
def get_chunks(stream, chunk_size, num_chunks):
for _ in range(num_chunks):
yield np.asarray(stream.read(chunk_size))
def filter_chunks(stream):
for chunk in get_chunks(...):
if is_interesting(chunk):
yield chunk
Code: Alles auswählen
chunks = filter(is_interesting, get_chunks(stream, chunk_size, num_chunks))
Hallo zusammen
das funktioniert übrigens sehr gut!
Jetzt steht die nächste Herausforderung an. Ich möchte ein zweites Mikrofon hinzufügen. Da meine USB-Soundkarte nur einen Mono-Eingang hat, habe ich mir eine zweite gekauft... nun ist die Frage ob es eine Möglichkeit gibt, paralell von 2 Soundkarten aufzunehmen...?
Ich habe mal einen Hinweis auf pyjack gefunden... das Ding ist aber nicht Dokumentiert und so für mich nicht einsetzbar...
Jemand eine Idee...
Irgendwie sowas wie
geht nicht, oder?
Lieber Gruss
das funktioniert übrigens sehr gut!
Jetzt steht die nächste Herausforderung an. Ich möchte ein zweites Mikrofon hinzufügen. Da meine USB-Soundkarte nur einen Mono-Eingang hat, habe ich mir eine zweite gekauft... nun ist die Frage ob es eine Möglichkeit gibt, paralell von 2 Soundkarten aufzunehmen...?
Ich habe mal einen Hinweis auf pyjack gefunden... das Ding ist aber nicht Dokumentiert und so für mich nicht einsetzbar...
Jemand eine Idee...
Irgendwie sowas wie
Code: Alles auswählen
audio = pyaudio.PyAudio()
stream = [audio.open(input_device_index=1),audio.open(input_device_index=2)]
data =np.hstack(stream.read(CHUNK) for in range (num_CHUNK)
Lieber Gruss
Fuer mehrere Devices wirst du ueber callbacks gehen muessen, denn jedes von denen hat seine eigene Zeitbasis & ggf. andere Aspekte wie zB Buffergroesse etc.
Eine Alternative waere ein Audio-Device das mehrere Kanaele unterstuetzt, die bekommst du dann in einem Rutsch, und bist auch synchron.
Eine Alternative waere ein Audio-Device das mehrere Kanaele unterstuetzt, die bekommst du dann in einem Rutsch, und bist auch synchron.
Doch, eben genau das bekommst du dann. Du oeffnest zwei Geraete, und bekommst fuer jedes einen Rueckruf wenn es einen Audio-Buffer fuer dich hat. Den kannst du zB in eine Queue pappen, und in deinem Haupthread Buffer beider Devices verarbeiten.