C++ Wav-Datei Samples addieren
-
So das ist jetzt der neuste Stand vom Code.
#include <iostream> #include <stdio.h> #include <stdlib.h> template <class T> class Container{ private: T *myArray; int mySize; public: Container(unsigned int startSize){ mySize = 0; myArray = NULL; resize(startSize); } ~Container(){ if(myArray != NULL){ delete[] myArray; } } void resize(unsigned int size){ T *newArray = new T[size]; int t = 0; if(myArray != NULL){ for(t = 0; (t < size) && (t < mySize); t++){ newArray[t] = myArray[t]; } for(; t < size; t++){ newArray[t] = 0; } delete[] myArray; } myArray = newArray; mySize = size; } T &operator[](unsigned int index){ if(index < 0) printf("Index negativ \n"); if(index > mySize) resize(index + 1000); return myArray[index]; } };
Nun verstehe ich nicht wieso im Konstruktor mein myArray = NULL gesetzt wird und später in der resize-Methode es auf NULL überprüft. Ich meine es ist ja dann immer NULL durch den Konstruktor oder nicht?
Und wieso wird nirgendwo die &operator[]- Methode aufgerufen bzw. diese Methode verstehe ich nicht, bis auf dass es die rezise-Methode aufruft, um den neuen Array zu vergößern?
-
Was ist, wenn resize ein zweites Mal aufgerufen wird?
Dass die Methoden deines Containers nirgendwo benutzt werden, ist ja kein Wunder, solange du deinen Container nirgendwo benutzt.
-
@SeppJ Wenn die resize-Methode ein zweites mal aufgerufen wird, dann wird mein Index+1000 übergeben und anschließend newArray[index+1000] bzw. newArray[size] initialisiert. Danach werden die Werte vom erstenArray in das zweite Array übertragen.
Das heißt, dass die Operator-Methode immer aufgerufen wird oder wie?
-
Eigentlich sieht das gar nicht so schlecht aus, nur das Verhalten des []-Operators ist etwas merkwürdig. Normalerweise vergrößert der Aufruf den Container nicht, sondern wirft ´ne Exception oder sowas.
Welchen C++ Standard benutzt du? Kann dein Compiler schon min. C++11? Wenn ja kannst du die Initialisierung schon in den Header verschieben:template<typename T> class Container { T* myArray = nullptr; int mySize = 0; ... }
Die Zuweisung in Zeile 37 funktioniert nur für numerische Datentypen, wenn du zB
std::string
in deinem Container speichern möchtest erzeugt die Zeile einen Fehler. Du kannst stattdessennewArray[t] = T{};
schreiben, damit wird der default-Konstruktor des jeweiligen Datentyps benutzt. Für numerische Werte liefert der 0, abhängig vom Datentyp (also auch 0.0 und 0.0f).Ich persönlich würde ja für die Anzahl der Elemente und den Index einen positiven Ganzzahltypen nehmen, dann kann man sich die Überprüfung auf < 0 schenken.
PS:
Ne Überprüfung des Rückgabewerts vonnew
brauchst du nicht, der ist immer gültig oder es wird einstd::bad_alloc
geworfen.PPS:
In deinerresize
Methode lässt du negative Größen zu.
-
@DocShoe Danke dir. Ich bin mir da nicht sicher, aber ich glaube mein Prof. meinte, dass wir kein C++ 11 benutzen. Er hat auch auf seiner Seite ein extra Video zu C++ 11 und deswegen gehe ich davon aus, dass wir es nicht benutzen.
-
Habe nun mein Code oben geupdatet (kleine Änderungen).
Jetzt ist mein Problem (wie ganz am Anfang): Wie lade ich meine Wave-Datei in mein Container?
FILE *myFile; myFile = fopen("song.wav", "rb"); //Container <FILE> wavArray(1000); return 0;
Das ist der Code wie ich es vorhätte, also <FILE> anzugeben, aber dann kommt wiederum ein Fehler in der Container Klasse.
-
@Berkan046
FILE
ist der Descriptor/Handle der Datei, das ist nicht der Dateiinhalt. Du musst jetzt den Inhalt der Datei lesen und dir überlegen, was du eigentlich in deinem Container ablegen möchtest.
-
@DocShoe vielleicht so:
Container <char> wavArray(1000); FILE *myFile; myFile = fopen("song.wav", "rb"); if(myFile){ for(int index = 0; index < 1000; index++){ wavArray.myArray[index] = fgetc(myFile); }
-
@Berkan046
Ja, vielleicht. Vielleicht auch nicht. Keine Ahnung, das musst du doch wissen.Du liest immer genau 1000 Zeichen ein, was ist, wenn die Datei kürzer oder länger ist? Schlauer ist es, zuerst die Länge der Datei zu bestimmen und dann genauso viele Zeichen zu lesen.
Wenn du mit deinem Container weiterarbeiten möchtest wäre einesize()
Methode sinnvoll.Edit:
Ne, dein Schnipsel kann nicht funktionieren.myArray
ist privat, da kommste von außen nicht dran. Fängst du jetzt wieder an zu raten?
-
@DocShoe Nein habs gelesen, dass es private sei, ich habe es auf public umgeändert. Danke dir für den Tipp mit der Länge, aber ich habe es so verstanden gehabt, dass in meine Container Klasse mein Array immer automatisch vergrößert.
PS: Ich habe jetzt erstmal alle Atributte auf public umgeändert.
-
@Berkan046
Ganz schlechte Idee. Ganz schlecht. Wirklich. Lass die Implementierung privat und benutz´ die öffentliche Schnittstelle. Dadurch, dass du direkt auf den Rohspeicher statt des []-Operators zugreifst vergrössert sich dein Array nicht automatisch. Wie SeppJ schon sagte: Du musst genau wissen, was du tust, und nicht einfach rumraten und Codeschnipsel hin- und herschieben bis der Compiler keine Fehler mehr meldet.
-
@DocShoe Ok habs wieder zurück geändert. Ich habe von einer vorherigen Aufgabe einfache den Code kopiert um die Größe zu bestimmen.
struct Wav{ char ChunkID[4]; int ChunkSize; char Format[4]; char SubChunk1ID[4]; int Subchunk1Size; short AudioFormat; short NumChannels; int SampleRate; int ByteRate; short BlockAlign; short BitsPerSample; char Subchunk2ID[4]; int Subchunk2Size; }; union ReadWav{ struct Wav header; char c[44]; }; while(i < 44){ header.c[i] = fgetc(myFile); i++; } fclose(myFile); printf("%d", header.header.ChunkSize * 8 / header.header.BitsPerSample);
die printf- Ausgabe habe ich auf dem Netz gelesen, aber ich weis nicht ob die Formel stimmt.
-
Na dann probier mal fleißig weiter. Viel Glück.
-
@DocShoe danke. Ich weis ihr wollt, dass ich logisch voran gehen soll (was ich teilweise) mache, aber mit fehlt auch das Wissen um es logisch voranzugehen.
-
Danke an alle. Ich habe die Aufgaben dank euch lösen können.
-
@Berkan046 sagte in C++ Wav-Datei Samples addieren:
struct Wav{ char ChunkID[4]; int ChunkSize; char Format[4]; char SubChunk1ID[4]; int Subchunk1Size; short AudioFormat; short NumChannels; int SampleRate; int ByteRate; short BlockAlign; short BitsPerSample; char Subchunk2ID[4]; int Subchunk2Size; }; (...) printf("%d", header.header.ChunkSize * 8 / header.header.BitsPerSample);
die printf- Ausgabe habe ich auf dem Netz gelesen, aber ich weis nicht ob die Formel stimmt.
Dein
printf
gibt keinen sinnvollen Wert aus.header.header.ChunkSize
ist die Chunk-Size desRIFF
Chunks der die ganzen Daten desRIFF WAVE
Files enthält (RIFF
enthält alle Sub-Chunks, nicht nur dendata
Chunk).Weiters ist
header.header.BitsPerSample
die Anzahl der Bits pro Sample pro Kanal. Wenn du also die "Länge" des Wave Files wissen willst, dann müsstest du noch denNumChannels
Wert berücksichtigen. Alternativ kannst duBlockAlign
verwenden - das ist die Anzahl der Bytes pro Sample (alle Kanäle zusammen).Und die
struct Wav
trifft einige Annahmen über den Aufbau des WAV Files die nicht garantiert sind. z.B. muss derdata
Chunk nicht direkt auf denfmt
Chunk folgen. Ich weiss auch nicht ob die Grösse desfmt
Chunks immer gleich ist. Usw.
-
Dieser Beitrag wurde gelöscht!
-
@Berkan046 Jo Berkan hab die selben Aufgaben. Hab das gleiche Problem. Kannst du die Lösungen schicken?
Danke!
-
Hey Bruder, Schick mir auch!
-
Hi @timo und @MarvinDerBoss,
so kommt Ihr evtl. durch die Ausbildung, aber später im Arbeitsprozess, falls Ihr den anstrebt, werdet Ihr die Deppen sein.