Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Das Radioforum. Hier dreht sich alles um die technischen Seiten des Radio- und TV-Empfangs.
Gerhard G.

Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Gerhard G. »

Hallo allerseits,

wie ein Thread von Ende Januar zeigt, ist das Eurosignal noch nicht in Vergessenheit geraten -- im Gegenteil, es wurden sogar Mitschnitte davon gesucht. Mit solchen kann ich zwar nicht dienen, dafür mit einem Eurosignal "Marke Eigenbau". Das folgende Python-Skript erzeugt ein waschechtes Eurosignal (gemäß Spezifikation) als Wave-Datei. Die darin zu übermittelnden Nummern können zufällig erzeugt und in einer Textdatei mitprotokolliert oder alternativ aus einer Textdatei übernommen werden. Somit hat man die Möglichkeit, seine Lieblings-Nummernfolge mit ausgefeilter Melodik zu komponieren... :D
Hier nun das Skript zum über-die-Zwischenablage-in eine-Textdatei-kopieren (leider konnte ich den Code-Modus nicht verwenden, da dieser aus < und > < und > macht :mad: ):

--8<----------------8<----------------8<--
#!/usr/bin/env python

# eurosig.py -- generates a random or predefined Eurosignal as WAV file
# Written Feb 2005 by Gerhard Grimm <gerhard dot grimm at gmx dot net>
# Donated to the Public Domain. Have fun!

import sys
from math import *
import struct
import random

class EurosignalEncoder:
"Converts a sequence of 6-digit numbers to a Eurosignal PCM waveform"
freq = [979.8, 903.1, 832.5, 767.4, 707.4, 652.0, 601.0, 554.0, 510.7, 470.8, 1062.9, 1153.1]
duration = 0.1

def __init__(self, Rate, Load, Limit, NumFile, WavFile):
"Initialize internal encoder state and set parameters"
self.rate = Rate # samples per second
self.load = Load # 0.0 .. 1.0
self.limit = Limit # how many numbers to produce
self.count = 0
self.numfile = NumFile # text file with numbers, read in player mode,
# written in random generator mode
self.wavfile = WavFile # WAV file (PCM), always written
self.phase = 0.0

def EncodeDigit(self, Digit):
"Encode a single digit to PCM. 10 = repetition, 11 = pause."
pcm = ''
samples = int(self.duration * self.rate)
omega = 2 * pi * self.freq[Digit]
for n in range(samples):
t = n / float(self.rate)
sample = 32000 * sin(omega * t + self.phase)
pcm += struct.pack('<h', sample)
endphase = samples / float(self.rate) * omega + self.phase
self.phase = fmod(endphase, 2 * pi)
return pcm

def DigitSequence(self, Number):
"Encode a number to a digit sequence, looking for repetitions."
if len(Number) < 6:
return [10, 11, 11, 11, 11, 11, 11, 11]
digits = []
for i in range(6):
digit = int(Number)
if (i > 0) and (digits[-1] == digit):
digit = 10
digits += [digit]
return digits + [11, 11]

def WAVHeader(self):
"Provide the WAV header for the selected sample rate, 16 bit, mono."
return struct.pack('<4sL4s4sLHHLLHH4sL', 'RIFF', 36, 'WAVE', 'fmt ',
16, 1, 1, self.rate, 2 * self.rate, 2, 16,
'data', 0)

def NextNumber(self):
"Get the next number from input file or random generator."
if self.numfile.mode == 'r':
# Player mode
return self.numfile.readline()
# Random generator mode
self.count += 1
if self.count > self.limit:
return ''
result = ''
if random.random() < self.load:
for i in range(6):
result += chr(random.randint(48, 57))
result += '\n'
self.numfile.write(result)
return result

def DoGenerate(self):
"Perform the actual encoding."
self.wavfile.write(self.WAVHeader())
number = self.NextNumber()
while number:
for digit in self.DigitSequence(number):
self.wavfile.write(self.EncodeDigit(digit))
number = self.NextNumber()
# Adjust sizes in WAV header
size = self.wavfile.tell()
self.wavfile.seek(4)
self.wavfile.write(struct.pack('<L', size - 8))
self.wavfile.seek(40)
self.wavfile.write(struct.pack('<L', size - 44))

def Usage():
print 'Usage: eurosig.py <numbers file> <wav file>'
print '(to "play" an existing numbers file to a wav file)'
print 'or: eurosig.py <numbers file> <wav file> <# numbers> [<load>]'
print '(to generate a random sequence of numbers which will be logged'
print 'to a numbers file and "played" to a wav file -- load will be'
print 'assumed at 0.5 if not given)'

if __name__ == '__main__':
limit = 0
load = 0.5
if len(sys.argv) == 3:
# Player mode
num = open(sys.argv[1], 'r')
elif len(sys.argv) < 6:
# Random generator mode
num = open(sys.argv[1], 'w')
limit = int(sys.argv[3])
if len(sys.argv) == 5:
load = float(sys.argv[4])
else:
# wrong number of parameters
usage()
sys.exit(1)
wav = open(sys.argv[2], 'wb')
es = EurosignalEncoder(4000, load, limit, num, wav)
es.DoGenerate()
num.close()
wav.close()

--8<----------------8<----------------8<--

Die Skriptdatei sollte man "eurosig.py" benennen. Es läßt sich auf allen Plattformen benutzen, für die es auf http://www.python.org einen Interpreter gibt, also Windows, Unix, MacOS, ...
Hier ein Anwendungsbeispiel (Eingabeaufforderung starten und in das Verzeichnis wechseln, in dem das Skript liegt):

eurosig.py test.txt test.wav 100 0.6

Es erzeugt eine zufällige Folge von 100 Nummern (ca. 60 % davon werden tatsächlich Nummern sein, der Rest Pausen), schreibt sie in eine Datei test.txt und erzeugt die entsprechende Tonfolge als Datei test.wav (Spieldauer 80 Sekunden). Experimentierfreudige Naturen ;) können nun die Datei test.txt editieren (jede Zeile muss entweder leer sein oder eine 6-stellige Nummer enthalten) und mit

eurosig.py test.txt test.wav

die Auswirkungen ihrer Änderungen zu Gehör bringen. Viel Spaß!

Viele Grüße, Gerhard

P.S.: Übungsaufgabe für Nachrichtentechniker:
Schreibe eine Klasse EurosignalDecoder, die eine Wave-Datei mit Eurosignal einliest und eine Liste der übertragenen Nummern als Datei ausgibt. :eek:

WellenJäger

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von WellenJäger »

Bei mir klappt es nicht.

Stell doch die Text-datei online und erklär mal wie man das Verzeichnis wechselt.
Brubacker

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Brubacker »

WOW, WOW, WOW! Was für eine coole Sache...

Funktioniert einwandfrei bei mir!

Also absoluten Respekt für diese tolle Arbeit und ich würde sagen dass das unbedingt hier auf der Seite bei "Software" eingestellt werden muss (ist ja Public Domain).

P.S. Beim Aufruf muss vor das "eurosig.py" natürlich noch "python" stehen, da das Python-Skript natürlich nicht von selber ausführbar ist und auch zur Ausführung nicht kompliliert werden muss (sondern eben einfach mit dem Interpreter-Programm aufgerufen wird).

Günni74

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Günni74 »

Wie nennt sich denn die benötigte Software zum Erzeugen des Eurosignals?!?

Brubacker

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Brubacker »

Die benötigte Software steht oben in seinem Beitrag drin. Einfach rauskopieren und in eine Datei namens "eurosig.py" schreiben. Damit Du's ausführen kannst, brauchst Du aber einen Interpreter für die Programmiersprache "Python", in der das ganze Programm nämlich geschrieben ist (zu kriegen eben auf http://www.python.org).
Günni74

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Günni74 »

Die benötigte Software steht oben in seinem Beitrag drin. Einfach rauskopieren und in eine Datei namens "eurosig.py" schreiben.
Das war schon klar, aber wie heißt der Interpreter, kann ihn auf der HP nicht finden.

Gerhard G.

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Gerhard G. »

Hallo!

@WellenJäger: Mangels eigenem Webspace ging das nicht so einfach...
Wenn Du auf Windows die Eingabeaufforderung öffnest, erhältst Du normalerweise ein Prompt

C:\Dokumente und Einstellungen\WellenJäger>

Nehmen wir an, Du hast die Datei eurosig.py unter D:\Programme\ukwtv abgespeichert, dann gibst Du ein

cd /d D:\Programme\ukwtv

und erhältst ein Prompt

D:\Programme\ukwtv>

Nun kannst du die im Posting genannten Befehle ausprobieren!

@Brubaker: Danke für die Blumen! Natürlich dürft ihr das Skript ins Software-Archiv übernehmen (da ich neu hier bin, kannte ich es noch nicht). Bei der Installation von Python auf Windows wird übrigens die Dateiendung ".py" mit dem Python-Interpreter verknüpft, so dass man es tatsächlich wie ein normales Programm aufrufen kann, ohne den "python"-Befehl davor angeben zu müssen. Auf Unix genügt ein "chmod +x eurosig.py", um das Skript ausführbar zu machen, die erste Zeile im Skript führt die Shell dann zum Interpreter.

Viele Grüße, Gerhard

Gerhard G.

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Gerhard G. »

Hallo Günni74,

die genaue Download-URL ist
http://www.python.org/ftp/python/2.4/python-2.4.msi
für die aktuelle Version 2.4 unter Windows.

Viele Grüße, Gerhard

Günni74

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Günni74 »

Danke! Hatte die Datei anfangs ignoriert, weil ich mit der Endung msi nichts anfangen konnte, danke! Jetzt funzt es, echt geil!

Brubacker

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Brubacker »

Gerhard G. schrieb:
Bei der Installation von Python auf Windows wird übrigens die Dateiendung ".py" mit dem Python-Interpreter verknüpft, so dass man es tatsächlich wie ein normales Programm aufrufen kann, ohne den "python"-Befehl davor angeben zu müssen. Auf Unix genügt ein "chmod +x eurosig.py", um das Skript ausführbar zu machen, die erste Zeile im Skript führt die Shell dann zum Interpreter.
Ah, dass das unter Unix so geht, wusste ich nicht (bin in Linux nicht so wirklich versiert) und unter Windows hab ich noch nie was programmiert und ausgeführt, da ich das immer nur unter Linux gemacht hab.
WellenJäger

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von WellenJäger »

Bei mir klappt es immer noch nicht. Es erscheint "Syntax Error". Vielleicht hab ich den Text falsch kopiert. Schick mir doch einer mal seine eurosig.py Datei per E-Mail zu, vielleicht klappt es dann.
WellenJäger

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von WellenJäger »

Kommando zurück, hab den Fehler gefunden!

Die Eurosig-Datei hatte die Endung ".py.txt", deshalb wurde sie nicht gefunden. Wie konnte sowas nur passieren *kopfschüttel*

Ich bin vom Sound übrigens begeistert !!
Gerhard G.

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Gerhard G. »

Hallo WellenJäger,

die ungewollte ".txt"-Endung beim ersten Abspeichern kann man Notepad leider nicht abgewöhnen :mad: . Das ist genauso intelligent wie die Warnung, die man anschließend im Explorer erhält, wenn man die Datei dann umbenennen will: Sie könnte dadurch unbrauchbar werden! :joke:
Jedenfalls freut es mich, dass es jetzt auch bei Dir klappt. :D

Viele Grüße, Gerhard

Günni74

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von Günni74 »

Auf welcher Frequenz, bzw. auf welchen Frequenzen wurde denn dieses Eurosignal ausgestrahlt? Ich kann mich noch sehr gut an dieses Gepiepse erinnern, welches ich unterhalb 87.5 MHz empangen konnte. Das künstlich erzeugt Eurosignal klingt übrigends genauso wie früher. Die Niederländer hatten einen tieferen Klang!

DX-Project-Graz

Re: Für hartgesottene Eurosignal-Nostalgiker: Ein Python-Generatorskript

Beitrag von DX-Project-Graz »

Das ist ja saugeil!!! :-)

Antworten