laufende Signale ausgeben, wie vorgehen?
-
Also es handelt sich hier um ein allgemeines Problem, aber da es ein C++-Forum ist, kann ich meine Frage ja auch hier posten.

Ich möchte folgendes tun: WAV-Datei einlesen, sinnvoller weise gebuffert, und diese Datei nach allen Künsten der Idiotie bearbeiten. (Anders gesagt: filtern, komprimieren, grafisch ausgeben.
Ich habe bis jetzt schon eine Klasse die mir ne Datei einliest und dann die Samples in 1024-er Stücken in ein Array speichert.
Jetzt lautet die Frage, wie gebe ich das Ding aus? Ich möchte das Teil gerne in 512er oder vielleicht kleineren Blöcken ausgeben und dann den Bereich, der ausgegeben wird, verschieben.sprich:
|A|B|C|D| ist sichtbar, dann:
|B|C|D|E| und dann
|C|D|E|F| und so weiter.
jetzt hatte ich folgende Ideen:
- Ein Ausgabe-Array, dessen Größe direkt angepasst ist (hier z.B. 4) und welches nach jeder Ausgabe bearbeitet wird. (Verschiebe alle Elemente nach links, füge an der letzten Stelle ein neues Element ein.) (So wie oben zu sehen)
- Ein Ausgabe-Array, welches doppelt so Groß ist wie mein Ausgabe-Feld (hier z.B.
Während das Feld ausgegeben wird und stück für stück die Liste durchlaufen wird, wird ein neues Array erzeugt, welches mit den vorderen Teil Identisch ist. Also:
|A|B|C|D|E|F|G|H| und das zweite wäre |F|G|H|I|J|K|L|M| (man sieht schon, wo halt zum zweiten Array gewechselt wird.- Wieder zwei Arrays, wobei die Bereiche sich nicht mehr überschneiden. Es muss halt darauf geachtet werden, dass während der Ausgabe auf das Richtige Array zugegriffen wird. Also:
|A|B|C|D|E|F|G|H| und |I|J|K|L|M|N|O|P|, während das Zweite Array ausgegeben wird, ohne das noch Teile vom 1. benötigt werden, wird das 1. mit einem neuen Ausgetauscht. (|Q|R|S|....)- Möglichkeit 4, welche aber nicht so mein Fall ist: Immer noch eine Linie zeichnen zwischen dem Element [n-1] und [n], das Entstehende Bild wird dann gespeichert, nach links verschoben und wieder eine neue Linie gezeichnet. Die Lösung ist nur grafisch, gefällt mir deshalb nicht so gut.
Gibt es noch andere Methoden? Ich hoffe mein Problem ist verständlich. Ich habe ja schon Lösungen aber möchte es gleich so machen, wie es tatsächlich am sinnvollsten ist. (Hat ja alles Vor- und Nachteile)
Danke im Voraus
-
Ich verstehe nicht genau was du willst - geht es prinzipiell um sowas:
#include <algorithm> #include <iostream> #include <iterator> // Edit: Wieso binde ich <ctime> ein? int main() { char const arr[] = "ABCDEFGHIJKLMNOP"; char const *first = arr, *second = first + 4; while( second != arr + sizeof(arr) ) std::copy( first++, second++, std::ostreambuf_iterator<char>(std::cout.put('\n')) ); }?
Dafür brauchst du keinen Puffer. Zwei Iteratoren reichen doch.
ruhig_brauner schrieb:
- Möglichkeit 4, welche aber nicht so mein Fall ist: Immer noch eine Linie zeichnen zwischen dem Element [n-1] und [n], das Entstehende Bild wird dann gespeichert, nach links verschoben und wieder eine neue Linie gezeichnet. Die Lösung ist nur grafisch, gefällt mir deshalb nicht so gut.
Womit machst du das eigentlich? Wie mir gerade auffällt, nicht unbedingt mit der Konsole?
(Deine Lösung wäre zum animieren eines Übergangs sinnvoll)
-
Nicht mit Konsole.

Also wäre das Einlesen mit einem mal möglich, wäre das natürlich am sinnvollsten.
Nur leider ist ne 10-Minutige WAV-Datei mit 100+mb mein Ziel. Ich hab das ding gerade mal durchgerauscht und bin auf 28.014.592 Samples gekommen.
Beziehungsweise 27358 Puffer mit 1024 Samples.Die Frage ist nun, wie ich das Ding ausgebe und wie der Wechsel zwischen den Puffern aussieht.
-
ruhig_brauner schrieb:
Nicht mit Konsole.

Das Vorgehen von Sone ist inwiefern konsolenspezifisch?
-
SeppJ schrieb:
ruhig_brauner schrieb:
Nicht mit Konsole.

Das Vorgehen von Sone ist inwiefern konsolenspezifisch?
Er fragte, womit ich das machen wollte. Halt nicht mit Konsole.

-
Jetzt verwirrst du mich mit Begrifflichkeiten.
Heißt ausgeben: Du zeichnest etwas auf den Bildschirm? Bspw. Die Frequenzen?
Dann geht das wie ich gezeigt habe. Du hast ein großes Array mit Frequenzen und zwei (am Besten Random-Access*) Iteratoren darauf, die du in jedem Schritt um die gleiche Schrittweite erhöhst und dann den von ihnen eingeschlossenen Array-Teil irgendwie ausgibst.
Oder heißt ausgeben: Der Lautsprecher gibt die Samples aus?
~*Sonst musst du immer mit [c]std::advance[/c] Stück für Stück inkrementieren. Das wäre nicht gut.~
-
Sorry, ich saß in der Bahn.

Ich möchte auf dem Bildschirm zeichnen . Das, was du gezeigt hast, funktioniert natürlich mit einem Array. Das problem ist wirklich einfach nur, dass das Array zu groß wäre. Wie unten steht, 27 Millionen Elemente,... Statt dessen muss ja mit Puffern gearbeitet werden a 1024 Elemente.
Die Frage, die ich jetzt habe, ist, was passiert, wenn "second" nicht mehr im ersten Array ist. Es muss ja weiter ausgegeben werden, die Frage ist nur, wie. Das meinte ich mit meinen 3 Möglichkeiten.
1.) Wenn Second an die grenze stößt einfach auf das nächste Array wechseln, welches dort los geht, wo first vorher war. (Die Arrays überlappen sich also)
2.) Ne Funktion schreiben, die zeitweise aus beiden Arrays liest und dann wieder nur aus einem.
3.) Das Array wird komplett ausgedruckt. Nach jedem Drucken werden alle Elemente des Arrays nach links versetzt und in die entstehende freie Stelle ein neues Element geladen. (absolut ineffektiv^^)
-
2.) Ne Funktion schreiben, die zeitweise aus beiden Arrays liest und dann wieder nur aus einem.

Du lädst immer nur zwei Puffer gleichzeitig in den Speicher.
Sobald der zweite Puffer in meinem Algorithmus "betreten wurde", lädst du den dritten und löschst den ersten (und vertauschst die Zeiger entsprechend). Dann brauchst du nicht mehr als gleichzeitig zwei Puffer im Speicher zu haben.#include <iostream> #include <iterator> #include <algorithm> #include <cstddef> #include <limits> char const* put_concat( std::ostreambuf_iterator<char> os, std::ptrdiff_t step_width, char const* first, char const* last, char const* first2, char const* last2 ) { char const* rval; auto chars_left = last - first; if( chars_left < step_width ) { std::copy( first, last, os ); rval = first2 + step_width - chars_left; std::copy( first2, std::min(rval, last2), os ); } else { rval = first + step_width; std::copy( first, rval, os ); } return rval; } int main() { char const arr[][7]{ "ABCDEF", "GHIJKL", "MNOPQR", "STUVWX", "YZ" }; auto len = sizeof(arr) / sizeof(*arr); char const* cur_start = arr[0]; for( std::size_t index = 0; index != len; ) { auto cur_last = arr[index] + 6; cur_start = put_concat( std::cout.put('\n'), 4, cur_start, cur_last, arr[index + 1], arr[index + 1] + ( index == len - 1 ? 0 : 6 ) ); if( cur_start > cur_last ) ++index; } }
-
An sich schon aber das Funktioniert erstmal nur, wenn man immer nur ein Element braucht. Wenn man mehrere braucht, kann ich den letzteren Puffer erst wegschmeißen, wenn tatsächlich kein Element aus diesem mehr benötigt wird. In der Zeit muss ich aber schon auf den zweiten Puffer zugreifen,...