Fragen zum wave-Modul

Du hast eine Idee für ein Projekt?
Antworten
Benutzeravatar
Tmk
User
Beiträge: 4
Registriert: Montag 22. Februar 2010, 00:01
Kontaktdaten:

Hallo Pythonforum,

ich komme bei einem Projekt mit dem Programmieren in python3 nicht weiter.

Ich möchte Audiodateien zerhacken. Dabei gebe ich dem Programm eine Input.wav, diese soll in wählbar viele und wählbar lange Schnipsel zerlegt werden. Die Schnipsel werden von zufälligen Positionen aus der Input.wav heraus geholt und in einem Arbeitsordner durchnummeriert abgespeichert. In einem zweiten Schritt soll das Programm alle erstellten Schnipsel in zufälliger Reihenfolge aneinander hängen und als Output.wav abspeichern.

Soweit zur Idee. Nun komme ich an folgender Stelle nicht weiter: Ich weiß nicht, wie ich das Wave_write.writeframesraw(data) benutzen soll. Was genau ist dabei das "data"? Wie vermittle ich dem Programm, dass die Schnipseldateien sich ergeben sollen aus gewissen Frames der Input.wav? Und die zweite Frage, die sich später stellen wird, wie addiere ich die Schnippsel wieder zu einer neuen Output.wav?

Ich poste mal meinen bisherigen Fortschritt:

Code: Alles auswählen

# Mitschnitt Hakker
# Version 1
#
# Version Tmk zur Sichtung Ruben
#
# Stellen, an denen du die Ordnerstruktur fuer dich aendern musst sind markiert mit "#HIER" (4 Stellen)
#
# Aus Kompatibilitaet zu python2.6 sind hier keine Umlaute oder sz-ts drin.
#
# 2010-02-18, 2010-02-19

# Welcome
print('''''')
print('''=================''')
print('''Mitschnitt Hakker''')
print('''=================''')
print('''''')
print('''Mitschnitt Hakker zerlegt eine Wave-Audiodatei in kleine Schnippsel und frikkelt diese in zufaelliger Reihenfolge zu einer neuen Audiodatei zusammen.''')
print('''''')
print('''Die Eingabedatei kann alles sein, sie muss nur in "/home/<user>/Audio/" liegen, "Input.wav" heissen und eine Sounddatei sein. Und sie muss für das Python-Wave-Modul eine Sampling-Tiefe von 16 bit haben.''')
print('''''')

# Module laden
import os, sys, wave, random

# Datei laden
try:
    InputFile = wave.open('/home/tmk/Audio/Input.wav','r') #HIER
    print('''"Input.wav" gefunden, OK.''')
    print('''Sampling-Rate ist''',int(InputFile.getframerate()),'''Hertz.''')
    print('''Laenge der Datei ist''',int(InputFile.getnframes()) / int(InputFile.getframerate()),'''Sekunden =''',int(InputFile.getnframes()) / int(InputFile.getframerate()) / 60,'''Minuten =''',InputFile.getnframes(),'''einzelne Samples.''')
    print('''''')
except:
    print('''Erwartete "Input.wav" nicht in "/home/<user>/Audio/" gefunden.''')
    print('''Entweder der Ordner oder die Datei fehlen oder heissen falsch oder die Sampling-Tiefe ist ungleich 16 bit. Python's Wave-Modul kann nur 16 bit.''')
    print('''''')
    print('''Versuche es nochmal.''')
    print('''''')
    sys.exit()

# Auf Ordner /home/<user>/Audio/Schnippsel/ prüfen und ggfs anlegen (Arbeitsordner)
try:
    os.mkdir('/home/tmk/Audio/Schnippsel') #HIER
    print('''Lege Arbeitsordner "/home/<user>/Audio/Schnippsel/" an, OK.''')
    print('''''')
except:
    print('''Arbeitsordner "/home/<user>/Audio/Schnippsel/" gefunden, OK.''')
    print('''''')

# SchnippselLength
SchnippselLength = int(input('''Wie lang soll ein Schnippsel werden (in Sekunden)? '''))
if int(SchnippselLength) <= 0:
    print('''''')
    print('''Schnippsel koennen nicht kleiner gleich Null sein. Das geht einfach nicht. Danke fuers Probieren.''')
    print('''Versuche es nochmal.''')
    print('''''')
    sys.exit()
elif int(SchnippselLength) < int(InputFile.getnframes()) / int(InputFile.getframerate()):
    print('''''')
else:
    print('''''')
    print('''Schnippsel sollten kuerzer sein als die Eingabedatei.''')
    print('''Versuche es nochmal.''')
    print('''''')
    sys.exit()

# SchnippselAnzahl
print('''Bei richtig vielen Schnippseln, gemessen an der Laenge der Eingabedatei, werden sich die Inhalte, nicht 1 zu 1, aber doch, wiederholen.''')
SchnippselAnzahl = int(input('''Wie viele Schnippsel sollen von zufaelligen Positionen aus der Eingabedatei herausgeholt werden? '''))
print('''''')
if int(SchnippselAnzahl) <= 0:
    print('''Hole''',int(SchnippselAnzahl),'''Schnippsel.''')
    print('''OK, fertig.''')
    print('''''')
    sys.exit()
else:
    print('''Zerhacke "Input.wav" in''',int(SchnippselAnzahl),int(SchnippselLength),'''Sekunden lange Schnippsel. Bitte warten...''')
    print('''''')

# bis hier ist alles cool.
# ab hier weiß ich noch nicht so recht weiter...

# Zerhakken
i = 1 # das ist für die Dateinamenerzeugung der Schnippsel und zur Anzeige der Durchlaufsnummer. Ich liebe Konsolenoutput! :-)
while int(SchnippselAnzahl) > 0:
    r = random.randint(1,round(int(InputFile.getnframes()) - int(InputFile.getframerate()) * int(SchnippselLength))) # Erzeugt die Zufallszahl - SchnippselLength in Frames
#    InputFile.setpos(r)
#    OutputFile.setparams(2,2,int(InputFile.getframerate()),(wie viele samples))
    # Recorde von Stelle InputFile.setpos(r) + SchnippselLength in Frames nach BetweenFile --- kein plan bis jetzt wie...
    BetweenFile = wave.open('/home/tmk/Audio/Schnippsel/schnipp'+str(i)+'.wav','w') #HIER
    BetweenFile.setnchannels(2)
    BetweenFile.setframerate(int(InputFile.getframerate()))
    BetweenFile.setsampwidth(2) # 2 = 2 Byte = 16 Bit also OK
    print('''Durchgang Nummer''',int(i),'''- Extrahiere''',int(SchnippselLength),'''Sekunden ab Frame''',int(r))
    print('''''')
    SchnippselAnzahl = int(SchnippselAnzahl) - 1
    i = int(i) + 1

# Zusammensetzen
OutputFile = wave.open('/home/tmk/Audio/zerhakkt.wav','w') #HIER
OutputFile.setnchannels(2)
OutputFile.setframerate(int(InputFile.getframerate()))
OutputFile.setsampwidth(2)
# randommaessig aus den int(SchnippselAnzahl) Stuecken 1 neue wav bauen, sodass alle Schnippsel 1 mal drin vorkommen.


# Dateien schließen! jeht irgendwie nicht...
InputFile.close()
BetweenFile.close()
OutputFile.close()

# Verabschiedung
Für Hilfe und Anregung wäre ich dankbar.
LG, Tmk.
Zuletzt geändert von Tmk am Mittwoch 24. Februar 2010, 11:58, insgesamt 1-mal geändert.
Benutzeravatar
Tmk
User
Beiträge: 4
Registriert: Montag 22. Februar 2010, 00:01
Kontaktdaten:

Hallo,

ich bin schon ein bisschen weiter gekommen, habe "Wave_read.readframes()" gefunden, mit dem ich später die Frames aus der Input.wav rausholen kann, die ich haben mag. Jetzt spiele ich damit rum und frage mich, wie ich diese extrahierten Frames, die ein "String of Bytes" sind, in ein Integerformat wandeln kann, damit "Wave_write.writeframes()" funktioniert. Weiß das jemand?
[i]Du sollst nicht glauben, was du liest.[/i]
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Damit du vernünftige Hilfe bekommst, solltest du zwei/drei Dinge beachten:
- Es gibt für Codetags eine spezielle Python-Variante. Hänge dazu an das "code" einfach noch ein "=py" an. Dann liefert die Anzeige auch eine bunte Ausgabe
- Wenn du viel Code hast, dann poste diesen nicht direkt im Forum (man kann dann unter Umständen nicht mehr auf deine Frage antworten) sondern in einem Pastebin wie zum Beispiel http://paste.pocoo.org/.
- Mit Minimalbeispielen erhöhst du deine Chancen auf eine Antwort dramatisch. Zeige also nur den notwendigen (und lauffähigen!) Code, ohne allen überflüssigen Ballast wie Zusatzfunktionen oder deine geschätzten 100 Zeilen print-Anweisungen

Und noch einige allgemeine Hinweise zu deinem Code:
- Schreibe keinen Code auf Modulebene, verpacke alles in handliche Funktionen und benutze den ``if __name__ == "__main__"``-Guard. So kannst du deine Module auch importieren und sie werden nicht immer ausgeführt.
- Halte dich doch bitte an PEP 8. Python ist kein Java ;-) Und wenn du nach Hilfe fragst, dann vereinfacht das anderen das Verstehen deines Codes.
- Du solltest Berechnung und Anzeige trennen, momentan wirfst du alles wild durcheinander.
- Entscheide dich für entweder vollständig deutsche Namen oder vollständig englische. Beides durcheinander zu würfeln ist kein besonders guter Stil.
- Strukturiere deinen Code vernünftig. Was du produziert hast, kann kein Mensch vernünftig lesen ;-)
- Kommentare sollten einen Mehrwert haben und nicht einfach so existieren, damit man Kommentare hat
- "# Dateien schließen! jeht irgendwie nicht... " WTF?!

Und zu deiner eigentlichen Frage: Schau dir mal das struct-Modul an.

Hoffentlich helfen dir die Tipps ein wenig weiter, auf jeden Fall bist du damit ein wenig beschäftig ;-) Bis dann, Sebastian
Das Leben ist wie ein Tennisball.
BlackJack

Zur eigentlichen Frage würde ich eher vermuten das die Möglichkeit zu Lesen wohl das gleiche Format der Daten liefern sollte, wie die Möglichkeit zum Schreiben erwartet. Alles andere wäre eine ziemlich komische, asymmetrische API. Ich sehe jetzt nicht wo man da `struct` bräuchte. Die Daten sollen ja nicht verändert werden -- nur kopiert.

Ansonsten stimme ich EyDu voll zu -- der Quelltext sollte etwas strukturierter sein, und in sinnvolle Funktionen aufgeteilt werden. Denn da gibt es sicher Teile die man an mehreren Stellen benötigt, zum Beispiel das "kopieren" der Formatdaten von einer vorhandenen Wave-Datei in eine Neue, bevor man da Daten reinschreiben kann.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich bin mir sicher gelesen zu haben, dass Bytes in Integers geändert werden sollen... Es war aber auch fast schon 15 Uhr und ich habe noch keinen Kuchen gegessen, da können einem solche Fehler mal unterlaufen.

Sebastian
Das Leben ist wie ein Tennisball.
Benutzeravatar
Tmk
User
Beiträge: 4
Registriert: Montag 22. Februar 2010, 00:01
Kontaktdaten:

Ok, ich werd' Hausaufgaben machen gehen. Könnte, wie schon bemerkt, 'ne Weile dauern. Danke für den "code=py" Hinweis, hab mich schon gefragt, wie das die anderen gemacht haben. Wie funktioniert dieser Pastebin? Ich packe das da rein und verlinke von hier? Über "struct" bin ich auch gestolpert, leider funktionert das nicht richtig hier auf dieser 64bit Maschine. Danke für eure Antworten, ich bemühe und melde mich.
[i]Du sollst nicht glauben, was du liest.[/i]
Benutzeravatar
Tmk
User
Beiträge: 4
Registriert: Montag 22. Februar 2010, 00:01
Kontaktdaten:

Es ist geschafft! Es funktinoiert! Es zerhackt die ihm gegebene Input.wav in Schnipsel und fügt sie schrittweise zu einer neuen Datei zusammen. Das klingt zuweilen echt freakig, je nachdem, womit man es füttert.

Das Problem war, dass es OutputFile.setnframes() vor dem OutputFile.writeframes() verlangt, und ich nach drei Wochen erst auf diesen Trichter gekommen bin...

Ergebnisse gibt's bald auf meiner Netzseite, ich werd's posten, wenn es soweit ist. Vielen Dank für die angebotene Hilfe!

LG'st
Tmk
[i]Du sollst nicht glauben, was du liest.[/i]
Antworten