Klirrfaktor messen - zu Fuß...
#1
Hallo,

im Sommer habe ich an anderer Stelle hier im Forum eine Themenfremde Diskussion rund um den Klirrfaktor und seine Messung angestoßen. Da ich Peters großartigen Thread nicht wieder mißbrauchen will, hier an dieser Stelle nun ein ein kleiner Fortschrittsbericht:

Hintergrund ist, dass ich gerne die üblichen Kenndaten von Magnetbändern ausmessen möchte, und dabei möglichst viele mit der Soundkarte erledigen möchste. Als bekennendem Linux-Nutzer ohne greifbaren Windows-Rechner steht mir auch der allseits beliebte Audiotester nicht zur Verfügung. Gleichzeitig will ich auch eine hohe Automatisierbarkeit hinbekommen, dass später nicht jede Messung in viel Handarbeit mündet. Deswegen versuche ich nun, die Messgrößen gut genug zu verstehen, um sie entsprechend nachbauen zu können. Mittel der Wahl ist dabei Python, ergänzt um den üblichen Stack aus numpy und SciPy.

Hier nun also der Klirrfaktor: Ich habe mich für die Variante entschieden, einen Bandpassfilter um den dritten Teilton zu legen und danach wieder dessen Effektivwert zu bestimmen. Bei einem Grundton von 1 kHz habe ich einen Durchlassbereich von 2900 bis 3100 Hz und einen Butterworth-Filter 3. Ordnung verwendet.

Damals hat Ulrich ein paar Audiobeispiele generiert, die den dort diskutierten Zahlenbeispielen folgen. Diese habe ich nun als Test verwendet, um zu sehen, ob ich auch den richtigen Klirr messen kann. Das geht mit folgendem Beispiel-Code:

Code:
# coding: utf-8

import numpy as np
from scipy.io import wavfile
from scipy.signal import butter, lfilter

def main(filename):
    fs, data = read_wav(filename)
    db_sig, db_h3, k3 = calc_k3(fs, data)
    print '{:22}: total {:2.1f}dB, h3 {:2.1f}dB, k3 {:5.2f}%'.format(
        filename, db_sig, db_h3, k3
    )

def read_wav(filename):
    fs, samples = wavfile.read(filename)
    return fs, samples2float(samples)

def samples2float(data):
    # divide by the largest number for this data type
    return 1. * data / np.iinfo(data.dtype).max

def calc_k3(fs, data):
    h3 = filter_h3(fs, data)
    return db(rms(data)), db(rms(h3)), 100. * rms(h3) / rms(data)

def filter_h3(fs, data, f1=2900, f2=3100):
    w1 = f1 / 0.5 / fs
    w2 = f2 / 0.5 / fs
    b, a = butter(N=3, Wn=[w1, w2], btype='band')
    return lfilter(b, a, data, axis=0)

def db(x):
    return 20 * np.log10(x)

def rms(x):
    return np.sqrt(np.sum(x**2, axis=0) / len(x))

if __name__ == '__main__':
    main('1k+3k75+25Summe.wav')
    main('1k+3klr97+3summe.wav')
    main('1k+3klr3ProzSumme.wav')

Eigentlich steckt die Arbeit nur im Hin- und herschieben von Samples und dem Ausgeben von Ergebnissen - die Filter selbst bringt SciPy schon mit (in form von scipy.signal.butter und scipy.signal.lfilter). Auch das Einlesen von wav-Files (wenn auch nicht ganz ohne zu meckern) macht scipy.io.wavfile. Ich hoffe, der Code ist einigermaßen verständlich - sonst erkläre ich auf Anfrage gerne noch die Details. Auf Ulrichs Beispiele angewendet, kommt folgendes raus:

Code:
1k+3k75+25Summe.wav   : total -5.1dB, h3 -15.1dB, k3 31.61%
1k+3klr97+3summe.wav  : total -3.3dB, h3 -33.5dB, k3  3.09%
1k+3klr3ProzSumme.wav : total -3.0dB, h3 -33.5dB, k3  3.00%

Dabei ist die erste Zahl der RMS des gesamten Signals, die zweite des gefilterten, und die letzte der Klirrfaktor. Die Werte entsprechen meiner Erwartung - so funktioniert es also Smile

Nebenbemerkung: Außerdem kommt noch eine Warnung raus: "WavFileWarning: chunk not understood" - das tritt auf, wenn das wav-File noch meta-Informationen oder andere nicht-Audio-Blocks enthält. Wenn man die Dateien mit einem Audioeditor davon befreit, verschwindet auch die Warnung. Das ist eine der Limitierungen von scipy.io.wavfile - die andere schlägt bei 24Bit-Files zu: Weil es keinen nativen Datentyp gibt, der 3 Byte groß ist, werden diese nicht unterstützt. Meine Abhilfe ist auch hier, sie per Audioeditor auf 32 oder 16 Bit zu konvertieren. Es gäbe auch noch andere Libraries, um Audiofiles zu lesen - das war mir aber bisher zu umständlich, da ich mit diesen Limitierungen ganz gut auskomme.

Wo soll das hinführen? Hier eine kleine Vorschau:

   

Solche Grafiken findet man in manchen Emtec- und RMG-Datenblättern, z.B. zum SM 468 oder SM 911. Sie zeigen den Anstieg des Klirrfaktors mit dem Ausgangspegel, und an den Schnittpunkten mit der 1% bzw. 3%-Linie kann man dann die Aussteuerungsgrenze MOL ablesen.

Diesen Plot hier habe ich halbmanuell erzeugt - besonders die Auswertung war noch ein "interaktiver Prototyp" in einer python-Shell, noch kein fertiges Programm. Das Prinzip: Audiodatei mit Sinus generieren, der auf der dB-Skala linear ansteigt, vom Rechner über Band wieder in den Rechner, und dann in kleinen Zeitscheiben jeweils die obige Logik laufen lassen. Gesamtdauer war hier 5 Sekunden, jedes Intervall 0.1 Sekunden lang. Hier könnte man sicher noch ein wenig nachjustieren - besonders im interessanten rechten Bereich ist die Steigung pro Bin doch schon steiler als wünschenswert. Vielleicht mach auch ein auf linearer Skala ansteigender Ton mehr Sinn, um dort mehr Auflösung zu bekommen.

Ich traue dem Zustand des Bandgeräts und seiner Einmessung nicht vollständig, deswegen verrate ich die weiteren Details nur unter der Auflage, dass Ihr nicht zuviel in die Ergebnisse hineininterpretiert, was nicht drinsteckt: ASC AS 4502, Onboard-Soundkarte meines Rechners, 96 kHz Sampling-Rate, DP 26 (schwarzer BASF-Karton, mit Rückseitenbeschichtung), 9.5 cm/s, 0dB = ca. 257 nWb/m, Messfrequenz 315 Hz.

So, Kommentare und Fragen willkommen!

Viele Grüße
Andreas
Zitieren


Nachrichten in diesem Thema
Klirrfaktor messen - zu Fuß... - von andreas42 - 11.11.2016, 23:59
[Kein Betreff] - von kaimex - 12.11.2016, 14:29
[Kein Betreff] - von andreas42 - 12.11.2016, 21:18
[Kein Betreff] - von Peter Ruhrberg - 12.11.2016, 21:37
[Kein Betreff] - von kaimex - 12.11.2016, 22:24
[Kein Betreff] - von kaimex - 13.11.2016, 12:57
[Kein Betreff] - von andreas42 - 13.11.2016, 23:59
[Kein Betreff] - von kaimex - 14.11.2016, 02:31
[Kein Betreff] - von andreas42 - 15.11.2016, 23:14
[Kein Betreff] - von kaimex - 16.11.2016, 13:08
[Kein Betreff] - von kaimex - 17.11.2016, 22:49
[Kein Betreff] - von andreas42 - 18.11.2016, 00:22
[Kein Betreff] - von Joseph von Arimathäa - 18.11.2016, 01:55
[Kein Betreff] - von kaimex - 18.11.2016, 10:23
[Kein Betreff] - von kaimex - 04.12.2016, 13:08

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 5 Gast/Gäste