liebes forum,
ich bin gerade dabei meine ersten filterfunktionen zu implementieren.
dabei habe ich folgende designkriterien:
16kHz abtastfrequenz, LP, HP, BP, Echo, sowie eine Impulsantwort, die 2
sekunden lang ist, mit 16kHz abgetastet wurde (also 32k Koeffizienten
besitzt) und die nachhallzeit 2sek. betragen soll.
die koeffizenten für LP, HP und BP habe ich mir per fdatool von matlab
berechnen lassen.
Nachdem ich die ersten drei Filter geschafft habe, treten folgenden
Probleme auf:
1. bei allen Filtern klirrt der Ausgang (könnte das eventuell daran
liegen, dass ich meine Eingangsignale nicht mit einem analogen LP
vorfiltere (aliasing-effekt?))
2. ab einer koeffizientenanzahl von |bi|>60 fängt das filter an zu
spinnen, es hört sich schrecklich an bis es wird fast vollständig
unterdrückt.
das board schafft bis zu 1,6 GFLOPS/sek., daran sollte es also nciht
scheitern.
ein codeauszug ist der folgende (einigermaßen kommentiert, benutze einen
ringbuffer, der so groß ist, wie es koeffizienten gibt). das gesamte
projekt hängt als zip hinten dran:
1
/*main-Funktion*/
2
voidmain()
3
{
4
DSK6713_AIC23_CodecHandlehCodec;//Erstellen eines Codecobjektes
5
DSK6713_AIC23_Configconfig=DSK6713_AIC23_DEFAULTCONFIG;//Erstellen einer Conifgurationsdatei
6
hCodec=DSK6713_AIC23_openCodec(0,&config);//Codec starten
7
DSK6713_AIC23_setFreq(hCodec,fs);// Set codec frequency to 16KHz
8
DSK6713_init();//DSP initialisieren
9
DSK6713_DIP_init();//Schalter initialisieren
10
//
11
for(k=0;k<test_i;k++){
12
circ_buffer[k]=0;
13
}
14
//
15
while(1)
16
{
17
if(DSK6713_DIP_get(0)==0)
18
{
19
floatsamples[41];//sample-array
20
floatresult=0.0;//Ergebnisvariable zur Summation
21
while(!DSK6713_AIC23_read(hCodec,&data));//lesen des Eingabestreams
while(!DSK6713_AIC23_write(hCodec,(short)result));//schreiben des Ausgabestreams
31
}
32
//...
33
//analog dazu die anderen beiden Filter, nur mit einem anderem filterarray
34
//...
35
else
36
{
37
/*Durchlass wenn kein Schalter gedrückt wird*/
38
while(!DSK6713_AIC23_read(hCodec,&data));
39
while(!DSK6713_AIC23_write(hCodec,data));
40
}
41
}
42
}
Es scheint ja ein grundlegendes Problem vor zu liegen, aber ich weiß,
als Anfänger, einfach nicht wo ich ansetzen soll.
Noch eine Frage zum Board:
Ist es prinizpiell möglich, die Eumlatorpins dafür zu verwenden um dort
Schalter anzulöten und diese dann iwie verwenden zu können? Das könnte
man eventuell mit Interrupts lösen, wenn der Schalter gedrückt (also ein
Kanal frei geschalten ist), dann Interrupt der jeweiligen Filterroutine.
Zu Interrupts habe ich bezüglich meines Boards und Filtern auch schon
etwas gelesen, aber ist das zwingend notwenidg? Läuft das ganze dann
besser, also ist das auch mein obiges Problem mit dem Klirren und den
hohen Koeff.anzahlen?
Bin dankbar für jede Antwort!!!
Grüße
Andre
sry den anhang und ein paar infos vergessen.
ich benutze das code composer studi 3.1 und matlab r2013a.
Beim dsp-board verwende ich den eingang line-in und den ausgang
line-out, jweils mit stereo 3,5mm klinke steckern.
Andre Richter schrieb:> 1. bei allen Filtern klirrt der Ausgang (könnte das eventuell daran> liegen, dass ich meine Eingangsignale nicht mit einem analogen LP> vorfiltere (aliasing-effekt?))
Probier erstmal mit einer einfachen Loop-Through Funktion vom Eingang
zum Ausgang, wie hoch die Aussteuerbarkeit ist und der Frequenzgang.
Wenn die Samplerate wirklich nur 16kHz beträgt, ist ein AA-Filter am
Eingang unvermeidbar, um alles über 8kHz abzuschneiden.
Dann implementiere ein Filter (das kannst du immer noch auf Multi-Tap
erweitern) und teste dieses.
danke für die antwort!
ich habe jetzt das ganze mal mit einer samplerate vn 48khz versucht,
womit der AA-effekt ja eigentlich behoben sein sollte, da mein
beispielsample von einer CD stammt, welche ja dann keine höheren
frequenzen als 22khz enthalten dürfte. trotzdem besteht weiterhin das
problem
grüße
Andre Richter schrieb:> result += lowpass[a]*samples[a]; //Multiplikation & Aufsummierung
Dir fehlt hier eine Skalierung. Wenn du bspw. 2 Samples mit je 48 bit
multiplizierst, kann da ein Ergebnis mit 96 bit Breite herauskommen, was
dann am Ausgang clippt bzw. übersteuert.
Die Abtastrate lass ruhig gleich bei 48kHz, damit bist du auf der
sicheren Seite.
Wie klingts denn (und wie ist der Pegel), wenn du per DIP Schalter den
unteren Teil des Programmes, also die Loop-Through Funktion, benutzt?
Solange du den AD/DA Wandler nicht überfährst, sollte das nämlich gut
klingen.
ja also bei nem tiefpass mit 41 koeffizienten und fstop von 1000khz,
filter er sauber bzw lässt durch...klingt auch sehr sauber, selbst bei
der musik, da klirrt nix. aber wehe dem ich man erhöht die koeff-anzahl,
dann geht es los. das mit dem konvertieren probiere ich mal. danke schon
mal
grüße :)
ich habe noch eine frage...
ich habe hier eine 6 sekunden lange wav, die die impulsantwort einer
kirche enthält...unter matlab nutze ich einfach den befehl conv und
schon ist mein aufgenommenes stücken ton mit dem kirchenhall belegt...
meine frage:
geht das überhaupt unter echtzeit mit einer zeitbereichsfaltung???
Hi Andre,
6 Sekunden Impuls in Echtzeit falten ist etwas zuviel und bei einer
Kirche auch etwas "überdosiert". Ich würde die Echos mit Delays
nachmodellieren und nur den ersten Sekundenbruchteil bis die
Koeffizienten gegen Null gehen mit einem FIR realisieren. Kannst du auch
stückweise machen.
Der Fehler, der dabei entsteht, dürfte nicht hörbar sein, gegenüber dem
sicher auch nicht perfekten Impuls.
Andre Richter schrieb:> geht das überhaupt unter echtzeit mit einer zeitbereichsfaltung???
Fitzebutze hats auch schon gesagt, du brauchst auf deinem System dann
Speicher für 6 Sekunden Samples und viele Outputpointer, um die Echos zu
simulieren. Beim Addieren der Pointer ist dann die Wichtung der Delays
entscheidend und natürlich das Feedback zum Original Signal.
Pionier in der Raumsimulation war eigentlich immer Quantec:
http://www.quantec.com/index.php?id=room_simulation&L=1
Nicht uninteressant.
An deiner Stelle würde ich jetzt mich erstmal auf 2 oder 3 Echopointer
beschränken und die Skalierung in den Griff bekommen.
Es hilft auch, das 'Clipping Overflow' Bit für Multiplikation zu setzen,
falls dein TMS320 das hat (mein alter TMS320C25 hats mit dem Mnemonic
'sovm'). Das sorgt dafür das Überläufe 'graceful' behandelt werden und
nicht zum kompletten Umschlagen des Resultates führen. Evtl. macht dein
Kompiler das schon, schau mal in den Projektoptionen.
Der Trick beim Multiplizieren oder Addieren besteht darin, es nicht zu
Überläufen kommen zu lassen. Das kann man z.B. so machen :
Hallo,
das Skalieren probiere ich morgen direkt aus!
Danke noch einmal für die hilfreichen Ansätze.
Ich hab den Code ja weitesgehend aus einem video-tutorial, aber auch in
anderen codequellen kommt es vor, dass result zum short gecastet wird,
obwohl die funktion AIC23_write als zweiten parameter ein unsigned in
erwartet?!?!
Und dann noch einaml zu den Echpointern? Google spuckt mir dazu nicht
viel brauchbares aus. Ich war der Meingung gelesene zu haben, dass sich
ein Hall auch mittels eines FIR-Filters realisieren lässt? Ich kann mir
aber auch grade gar nicht vorstellen, wie das Bodediagramm oder der
Frequenzgang dazu aussehen soll?
Habe die wave mal mit MATLAB downgesampled auf 16kHz, da ergeben sich
aber immernoch 96000 koeffizienten, viel zu groß alles -.-
grüße andre
Andre Richter schrieb:> Ich war der Meingung gelesene zu haben, dass sich> ein Hall auch mittels eines FIR-Filters realisieren lässt? Ich kann mir> aber auch grade gar nicht vorstellen, wie das Bodediagramm oder der> Frequenzgang dazu aussehen soll?
Ich denke, da verwechselst du was. Mit einem FIR kannst Filter basteln
aber für Echos musst du deine Samples im RAM speichern und nach einem
(justierbaren) Delay auslesen und mit dem Original (Dry) Signal mischen
und an den Ausgang legen.
Ich hab dir mal ein simples Echo in TMS Assembler angehängt. AR0 ist der
Outputpointer, AR1 der Input Pointer und AR2 der Outputpointer.
Andre Richter schrieb:> Ich war der Meingung gelesene zu haben, dass sich> ein Hall auch mittels eines FIR-Filters realisieren lässt?
Echo ist zwar auch eine Klangbeeinflussung, aber vor allen Dingen ein
Delay - du speichert das Orginalsignal und gibst es nach einer Delayzeit
wieder aus. Für regeneratives Echo speicherst du des Ausgangsignal
gemischt mit dem Original (DRY) als gewichtete Addition wieder in den
Samplepuffer. Wieviele Echos kommen, stellt du dabei vorher wieder über
eine Multiplikation mit einem 'Knob', also einem Skalierungsfaktor ein.
Wenn du am Ausgang auch noch das DRY Signal hören willst, mischt du ganz
am Anfang noch dein verzögertes Signal (WET) mit dem DRY.
Hier noch ein Tipp für viele Algorithmen:
http://www.musicdsp.org/showmany.php
Also in Assembler kenn ich mich nicht so gut aus.
Wenn man es anders begründen kann, könnte es ein FIR sein, nur dass die
Impulsantwort halt ein aufgenommener Teil von sich selbst ist (und der
Ausgang NICHT direkt zurück geleitet wird --> IIR) und dann einfach das
eingangsisgnal mit den aufgenommen schnipseln zeitlich versetzt
dazugefaltet wird, oder?
also wäre folglich mein erster schritt mir das eingangssignal auf dem
ram des tms320c6713 dsk für eine bestimmte länge zu speichern (hat da
vllt schon jemand erfahrung, wie ich den ram beschreiben kann?) und dann
muss ich das eingangssignal mit dem aufgenommenden und in der amplitude
verringerten signal aus dem ram falten und wieder auf den ausgang
schreiben. sind diese überlegungenr ichtig?
Zu dem Skalieren nochmal:
kann ich das skalieren weg lassen, wenn ich floats benutze? (darunter
stelle ich mir vor, dass ich float x = 3.234254353453E-05 schreibe)
ist es möglich beim skalieren a la >> 1 (also divison durch 2) einen
geeigneten paramter zu finden, der faustregelmäßig gut passt? vllt sowas
wie die filterlänge?
Grüße
Andre Richter schrieb:> also wäre folglich mein erster schritt mir das eingangssignal auf dem> ram des tms320c6713 dsk für eine bestimmte länge zu speichern (hat da> vllt schon jemand erfahrung, wie ich den ram beschreiben kann?)
Das machst du mit einem Ringpuffer, indem der Adresszeiger von RAMSTART
bis RAMEND läuft. Ist RAMEND erreicht, springt er wieder auf RAMSTART.
> und dann> muss ich das eingangssignal mit dem aufgenommenden und in der amplitude> verringerten signal aus dem ram falten und wieder auf den ausgang> schreiben. sind diese überlegungenr ichtig?
Halb richtig. Ein vom Eingangszeiger unabhängiger Ausgangzeiger
durchläuft ebenso RAMSTART bis RAMEND und liest den Wert und schickt ihn
auf den DAC. Gleichzeitig addierst du diesen Wert auf den Eingangswert -
Der Anteil dieses addierten Wertes bestimmt die Regeneration (Feedback).
Filter kommen hier erstmal nicht vor - das Echo hat den gleichen
Frequenzgang wie das Original. Der Abstand zwischen Eingangs- und
Ausgangzeiger bestimmt die Verzögerung des Echos (= Raumgrösse).
Hier hast du die längste Verzögerung, wenn der Ausgangszeiger immer
direkt vor dem Eingangszeiger läuft und den Wert des letzten Durchlaufs
ausgibt.
Im nächsten Schritt kannst du dann auf das Signal des Ausgangszeigers
ein Filter legen (FIR, IIR oder Biquad), bevor du das Signal auf den
Eingang addierst.
Arbeite dich aber erstmal durch den Echoalgorithmus, Filter kommt dann
später.
> Also in Assembler kenn ich mich nicht so gut aus.
Das ist hier auch nicht so wichtig, es geht nur um den grundlegenden
Ablauf.
Danke Matthias, ich werd mich durch arbeiten!
Das primäre Problem liegt jetzt allerdings noch in der stand-alone
Lösung, also dass ich den DSP mit Strom versorge und er mein Programm
automatisch lädt. Da bin ich aber grade noch am recherchieren auf den
TI-Wikis. Es sei denn jmd kennt eine schnell erklärte Lösung dafür oder
hat sogar schon ein Tutorial dafür.
Habe jetzt etwas bessere Ergebnisse für den FIR_Filter mit der Ordnung
100. Das Problem war die Modulorechnung, hab jetzt meinen Buffer mit
einer Größe einer Zweier-potenz und realisiere das ganze jetzt mit einer
UND-Verknüpfung.
[edit]: ich würde noch ganz gerne wissen, ob man für eine für das board
optimierte mac-operation (also addieren und multipolizieren in einem
takt) eine extra operation wählen muss oder es automatisch optimiert
abläuft oder es gar nur mit assembler zu realisieren ist?
Grüße und vielen vielen Dank noch einmal für die bisherigen Antworten.
Grüße
hallo, es gibt neuigkeiten...
ich habe jetzt komplett umgestellt...es kam die empfehlung, das ganze
mit einem pin-pong-buffer zu realiseren...das hab ich auch gemacht und
siehe da, tiefpassfilter mit 300 coeffs sind kein problem mehr!acuh das
echo funktioniert jetzt, mit der schleife:
nun würde ich gern noch ein etwas satteres echo haben wollen, also eines
was vllt einer faltung mit einer impulsantwort aus neiner kirche
entspricht, hat da jmd einen tip?
grüße
Andre Richter schrieb:> nun würde ich gern noch ein etwas satteres echo haben wollen, also eines> was vllt einer faltung mit einer impulsantwort aus neiner kirche> entspricht, hat da jmd einen tip?
Durch die vielen Wände in unterschiedlichen Abständen zur Quelle enthält
das Kirchenecho auch einen grossen Anteil Hall, je nach Kathedrale von
beträchtlicher Länge, plus natürlich einem nichtlinearen Frequenzgang.
(Klatsch mal im Kölner Dom in die Hände - gut ist vllt. nicht
angemessen, hehehe)
Meine Empfehlung mit
http://www.musicdsp.org/showmany.php
gilt aber immer noch.