sinus-sweep generieren
-
Hallo zusammen,
ich versuche, in C++ einen sweep zu generieren.
float fs = 48000; float f1 = 20; float f2 = 22000; float T = 4; vector<float> vOut_t; int length = fs*T; float value; float K = 2*PI*f1 * T / (log(f2/f1)); float L = T/log(f2/f1); float t, t2; for(t=0;t<length;++t) { t2=t/fs; value = exp(t2/L) -1; value = sin(K*value); vOut_t.push_back(value); }Wenn ich den sweep an die Soundkarte sende und ihn mir anhöre, klingt der Anfang (tiefe Frequenzen) wie erwartet. Aber wenn der sweep am Ende (hohe Frequenzen) ankommt, ist nicht mehr nur das reine sinus-Signal hörbar, sondern auch irgendwelche Überlagerungen.
Wenn ich den sweep (mit dem gleichen Algorithmus) in scilab implementiere, ihn in eine Textdatei schreibe, in vOut_t lade und dann an die Soundkarte (wie zuvor auch via ASIO )sende, hört sich der sweep perfekt an.
Den Algorithmus zur sweep-Erzeugung habe ich von http://pcfarina.eng.unipr.it/Public/Papers/134-AES00.PDF (Seite 6).
Ich verwende Visual C++ 2008 Express Edition.
Hat jemand eine Idee, wie ich das Problem lösen kann?
Leider habe ich keinen Server, auf den ich die Sounddateien zum Anhören hochladen kann.
Vielen Dank schonmal
jomammele
-
Mach mal ein vOut_t.reserve(length); das sollte schon einmal etwas Laufzeit sparen.
Verwende double statt float. Vielleicht hapert es dort.
-
Der Algorithmus wird für steigende Werte für
valuenumerisch instabil. Da hilft es entweder, wie Fellhuhn sagtedoublezu benutzen, oder den Algorithmus so zu ändern, dass er stabil wird. Aufgrund der nichtperiodizität des Arguments für den Sinus ist das leider gar nicht so einfach...
scilab rechnet vermutlich indouble-Precision.
-
Hmmm...
Man braucht ja keine Formel die das Argument für die Sinus-Funktion für ein beliebiges "t" ausrechnet. Es reicht ja wenn man das Argument für die Sinus-Funktion in der Schleife immer inkrementiert. Dann ist das Ganze relativ einfach.
Im Prinzip:
double t2 = 0.0; for (size_t sample = 0; sample < N; sample++) { double t = static_cast<double>(sample) / N; // 0 ... 1 double frequency = ...; // aus t errechnen double speed = frequency / samples_per_second; t2 += speed; if (t2 > 1.0) { double dummy; t2 = modf(t2, &dummy); } double value = sin(t2 * 2.0 * PI); out.push_back(value); }So lange nicht
speed << 1funktioniert das recht gut.
-
Hallo,
danke für den Tipp mit double. Dies behebt das Problem - allerdings reicht es nicht aus, nur den Typ von vOut_t und value zu ändern - sondern auch die anderen Variablen müssen vom Typ double sein.
Außerdem ist es ratsam, die Buffergröße der Soundkarte möglich hoch zu setzen, um Unterbrechungen in der Aufnahme zu vermeiden.
Vielen Dank für eure Hilfe
jomammele