Nun ist es der Wert 'vm', der mich interessiert. Um im Audiobereich zu arbeiten begrenze ich den Wert auf einen Bereich von 0-1. Das definiert ja dann die Amplitude.
Wenn ich nun eine Analyse des resultierenden Audiovektors mache, erhalte ich u.u. auch die Volumenwerte des Signals, in dB.
Nun meine Frage: kann ich das auch rückwärts machen. Sagen wir, ich möchte eine Sinusschwingung generieren mit einem Volumen von -10 dB. Kann ich diese -10 dB irgendwie in meinen bisherigen Code integrieren, so dass mir diese -10 dB den wert 'vm' ergeben?
Für einen Rat wäre ich sehr dankbar!
Liebe Grüsse,
Matthias
hab noch keine Erfahrung mit Audiosignale
aber ist 1 nicht equal 0 dB?
was ich auch nicht verstehe ist, die erzeugte sinus funktion hat negative Zahlen, wie kann man die negativen Zahlen in db umwandeln?
Ich bin auch ein "Laie" aber eine Schwingung im Audiobereich ist normalerweise zwischen 1 und -1. Alles darüber (positiv und negativ) wird geclipt. Sie schwingt immer um den 0-Punkt und positive und negative Werte ergeben die selbe Schwingungsenergie. Oder so ähnlich.
Wie beim Lautsprecher: +1=Membran voll raus, -1=Membran voll rein.
Und es gibt eben mehrere dB Skalierungen. In der Tontechnik arbeite ich mit 0 dB als Referenz und arbeite abwärts. Was ich bei der FFT analyse aber erhalte sind dB, die den Schalldruck angeben. Oder so. Da blicke ich auch noch nicht ganz durch. Das studiere ich momentan.
Was ich will: bei der FFT Analyse erhalte ich Volumenwerte zwischen ~ -80 und ~ +50. Genau diese dB Werte möchte ich nun in meinen Code als Wert für die Amplitude der Sinusschwingung implementieren. Geht das? Und wenn ja, wie?
Ich verstehe nicht was du machen möchtest? Was meinst du mit rückwärts...vom Frequenzspektrum zum Zeitsignal?
dB ist doch nur eine logarithmische Skalierung... -10 dB = 0.1
dB ist aber dimensionslos und hat immer einen Bezugswert. Bei einem Spannungspegel z.B: Lu = 20*ln(U/U0) [dBu]
Dass dB ein relativer Messwert ist mir klar. Auch dass es eine logarithmische Skalierung ist.
Wenn ich z.B. ein Spektrogramm eines Audiosignals betrachte sehe ich z.B. bei 300 Hz einen Spitzenwert von +30 dB. Ich will nun eine Sinusschwingung generieren mit einem Volumen von +30 dB.
Du schreibst, dass -10 dB = 0.1 ergibt. 0.1 wäre ja dann kompatibel zum Wert 'vm' in meinem Code. Vielleicht habe ich auch rechnerisch ein Riesenproblem in meinem Kopf. Denn:
-10 dB = 0.1
??? dB = 1.0
Wie geht diese logarithmische Skalierung? Ich denke die Mathematik ist mein Problem..
Ok, danke für die Formel. Aber das Problem ist noch nicht gelöst:
Mein originales Sample hat einen Spitzenwert von 0.57/-0.57 (ich habe es nicht normalisiert). Die Spektralanalyse ergibt mir einen Spitzenvolumenwert von 27.5532 dB.
Das wäre dann nach Deiner Tabelle ein Wert von über 10. Das überschreitet ja den Spitzenwert im Originalsample bei Weitem. Wie kann das sein? Ich kann ja keine Audiovektoren erstellen, die den Wert 1 überschreiten. Da wird alles über 1 geclipt.
Mein originales Sample hat einen Spitzenwert von 0.57/-0.57 (ich habe es nicht normalisiert). Die Spektralanalyse ergibt mir einen Spitzenvolumenwert von 27.5532 dB.
Dann erkläre doch bitte erst mal wie du auf diesen dB Wert kommst. Bei einem Sinus mit der genannten Amplitude
und einer Frequenz von 10 Hz, erhält man bei einem Frequenzspektrum mittels FFT (kein Leakage vorausgesetzt), einen Peak genau bei 10 Hz mit einem Amplitudenwert von 0.57 oder -4.88 dB. Falls nicht, stimmt die Skalierung nicht. Wenn du hier allerdings den Wert aus dem Spektrogramm angibst (danach hattest du ja in einem anderen Thread auch gefragt), kann ich dir nicht helfen. In der Matlab Funktion spectrogram() gibt es ja keine Skalierung und ich hatte dir einen möglichen Ansatz genannt. Evtl. zeigt sich nun, dass dieser falsch ist...auf Grund der überlappenden Segmente. Ich habe nach wie vor auch keine Erklärung finden können, war spectrogram die Amplitudenwerte nicht skaliert.
Die Umrechnung in dB und umgehrt ist jedenfalls korrekt.
EDIT: Ich habe dieses Post geschrieben bevor ich deine letzte Antwort gesehen habe.
Zitat:
Noch mal zur Klarifizierung:
Ich habe folgendes Audiosample mit Samplerate (fs) von 44100 Hz:
Dann benutze ich folgenden Code, um die Volumenverläufe bestimmter Frequenzen zu extrahieren (nur eine Annäherung an die tatsächliche Frequenz):
Code:
% This program is used to extract the volume envelope of a predefined % frequency (FQ) (it only returns an estimate around that frequency)
% import audio data first (data & fs) % define FQ: the frequency that you want to extract
% creates the window
w=hann(256, 'periodic');
% analyzes the data via FFT % spectrogram(data, window, noverlap, nfft(fftlength), fs) [S, F, T] = spectrogram(data, w, 128, 256, fs, 'yaxis');
% conversion of the values in S into dB
S_dB = 20*log10(abs(S)+eps); % eps is a small constant to prevent log(0)
% now look for all the values of the discrete frequency FQ % look for the closest discrete frequency next to x Hz (x=FQ)
F_discrete_idx = find(F >= FQ,1,'first'); % find delivers the index
% all amplitude values of the discrete frequency FQ along the time axis of T
volume_FQ = S_dB(F_discrete_idx,1:length(T));
Ich definiere jetzt FQ mal als 100 Hz. Da erhalte ich dann als resultat den Vektor 'volume_FQ'. Dieser hat den Spitzenwert von 27.5532 dB. Und sieht so aus:
Meine Frage jetzt: Wie kommt der Algorytmus vom Originalsample zu diesem Wert in dB? Und wie komme ich wieder zurück? Denn mit den ursprünglichen Werten in der Matrix 'S' zu rechnen erscheint mir merkwürdig und das funktioniert irgendwie nicht.
Ich möchte eine Sinuschwingung generieren, die bei einer Spektralanalyse ein Volumen von 27.5532 dB (ungefähr) ergibt, die aber im Audiovektor irgendwo zwischen den erlaubten Werten -1 und 1 liegt. Ausgangspunkt bleiben diese 27.5532 dB. Irgendwelche Rechnungsrundungen kann ich mir leisten und kann ich vernachlässigen.
Dann erkläre doch bitte erst mal wie du auf diesen dB Wert kommst.
Das habe ich mitlerweile nachgeliefert. Sorry für die zeitliche Überlappung.
DSP hat Folgendes geschrieben:
In der Matlab Funktion spectrogram() gibt es ja keine Skalierung und ich hatte dir einen möglichen Ansatz genannt. Evtl. zeigt sich nun, dass dieser falsch ist...auf Grund der überlappenden Segmente. Ich habe nach wie vor auch keine Erklärung finden können, war spectrogram die Amplitudenwerte nicht skaliert.
Vielleicht ist ja die spectrogram() Funktion nicht geeignet für meine Anwendung und ich brauche eine andere Herangehensweise.
In S bzw. Volume_FQ sind die Werte aber unskaliert...hast du mal getestet, was sich denn für dB-Werte ergeben, wenn du sie wie nach meinen beiden Vorschlägen skalierst?
Ich verstehe hier ohnehin noch nicht, was du hier machen willst...warum extrahierst du eine bestimmte Frequenz aus dem Spektrum? Warum der Zeitbezug bzw. reicht ein Frequenzspektrum mittels FFT nicht auch aus?
Ich meine mit skalieren aber etwas anderes...schau doch noch mal auf die beiden Vorschläge von mir in dem anderen Thread. Da sollte S durch die Segmentlänge geteilt werden bzw. ich hatte noch eine zweite Variante mit N/2 gepostet. Erst dann kommt die Umrechnung in dB. Nun würde mich mal interessieren, ob sich dann die -4.88 dB ergeben .
Ich hatte dir in dem anderen Thread ebenfalls die Berechnung von S bzw. den Aufbau der Funktion spectrogram() in einem Code gezeigt. Daraus sollte ja klar werden, wie S entsteht. Wenn du von diesem Spektrum wieder in den Zeitbereich willst, musst du mit der ifft() anstatt der fft() arbeiten.
Sorry für die späte Antwort. Ich habe mich noch mals über meine Codes gestürzt und bin zum Schluss gekommen, dass mir die spectrogram() funktion nicht die gewünschten Ergebnisse liefert. Sprich, sie sind zwar richtig, aber ich kann mit den Volumenwerten nichts anfangen.
Ich habe nun mit Hilfe der Matlab Hilfefunktion und Deinem Beispiel (was spectrogram() tut) einen neuen Code geschrieben, der mir überraschenderweise genau die Resultate liefert, die ich haben will. Die tatsächlichen Amplitudenwerte liegen genau zwischen 0 und 1. Ich habe den Code mit einer einfachen Sinuschwingung bei 10kHz getestet und die ergebnisse stimmen.
Nur bei der Fensterung verliere ich Amplitude. Ist ja auch logisch, denn der durchschnittliche Amplitudenwert sinkt ja durch die Fensterung. Ich kann das zur Zeit aber vernachlässigen, da sie ja alle proportional sinken. D.h. das Verhältnis zueinander stimmt. Vielleicht gibt es ja einen Weg, dies auszugleichen.
Hier ist mein neuer Code:
Code:
% this program returns 'abspec', the amplitude of the component frequencies of % the signal 'data'
% INPUT VARIABLES: % data = signal vector % fs = sampling rate
Offensichtlich hast du in dem anderen Thread nicht verstanden, was ich mit Skalierung meinte. Der hier angegebene Code rechnet auch nichts anderes als spectrogram(), nur dass du noch zusätzlich skalierst und auf die Umrechnung in dB verzichtest. Allerdings machst du hier noch 2 Fehler, was ich aber schon in dem anderen Thread erklärt hatte.
Der Gleichsignalanteil (DC) und die Amplitude bei der Nyquistfrequenz stimmen so nicht. Sie werden nicht mit 2 multipliziert .
Code:
[S, F, T] = spectrogram(data, w, 128, 256, fs, 'yaxis');
S = abs(S);
S_scale = [S(1,:)/N;S(2:end-1,:)/(N/2);S(end,:)/N];
% ob nun N/2 oder 2*S(2:end-1,: )/N ist ja gleich
Das sollte ja dann das Gleiche liefern, wie der obere Code. Mal abgesehen davon, das bei spectrogram der letzte Werte bei ungerader Anzahl nicht abgeschnitten wird.
Für die Amplitudenkorrektur durch die Fensterung kannst du mal folgendes testen...so wird es bei einem Frequenzspektrum mittels FFT gemacht. Wenn also die identische Skalierung beim Spektrogramm und dem Frequenzspektrum passt, sollte das so auch gehen.
Code:
% windowing of the segment
w_s = s(m:nfft+m-1).*win' * nfft / sum(win);
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.