Probleme bei schwieriger c++ Programmieraufgabe



  • Hallo, ich bin noch ein ziemlicher Neuling in Sachen programmieren und
    muss nun, zumindest für mich, schwierige Programmieraufgabe lösen:

    Es geht darum WAV Dateien in c++ zu manipulieren.

    -Die erste Aufgabe besteht darin, die "readWaveHeader" und
    printWaveheader" Funktionen so zu implementieren, dass sie
    Informationen zu einem WAV-File nach folgendem Schema ausgeben:

    Codec: PCM, 44100Hz, 16bitm 1 channel: Length 9.81 sec

    -In Aufgabe zwei soll die "readWaveHeader" so umprogrammiert werden,
    dass sie eine Fehlermeldung ausgibt, wenn eine WAV-Datei nicht die
    Eigenschaften:
    "Codec: PCM, 44100Hz, 16bit, 1 channel" erfüllt.

    -Dann soll als drittens die "writeWaveHeader" so implementiert werden,
    dass sie ein Waveheader in einen Output-Stream schreibt.

    -Dann ist noch angegeben, dass das Programm folgendes Unterstüzen
    sollte:
    1.) Wenn das Programm mit dem -totext Parameter aufgerufen wird, soll
    eine Textdatei (out.text) erzeugt werden, welche die einzelnen
    Samples(short) als ASCII Zahl auflistet.
    2.) Wenn das Programm mit dem -volume Parameter aufgerufen wird, soll
    das Programm die Lautstärke der Eingabedatei ändern. Ein float Parameter
    soll den Faktor angeben.
    3.) Wenn das Programm mit dem -mix Parameter aufgerufen wird, kann es
    zwei Audiodateien mischen.
    4.) Wenn das Programm mit dem -echo Parameter aufgerufen wird, soll ein
    Echoeffekt erzeugt werden. Der erste Parameter soll die Verzögerung, der
    zweite die Lautstärke des Echos angeben.

    Was ich bisher geschafft habe ist folgendes:

    [code]
    /********************************************************************
    	purpose:	A simple PCM Wave File Editing TOOL
    
    	created:	2010/11/08
    	filename: 	audio_tmpl.cpp
    	author:		
    
    *********************************************************************/
    
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <cstring>
    #include <limits.h>
    #include <stdlib.h>
    
    using namespace std;
    
    struct WAVEHEADER {
    	char	ChunkID[4];	//          Contains the letters "RIFF" in ASCII form
    	int		ChunkSize;
    	int		Format;
    	char	Subchunk1ID[4];
    	int		Subchunk1Size;
    	short	AudioFormat;
    	short	NumChannels;
    	int		SampleRate;
    	int		ByteRate;
    	short	BlockAlign;
    	short	BitsPerSample;
    	char	Subchunk2ID[4];
    	int		Subchunk2Size;
    };
    
    //---------------------------------------------------------
    // helper functions
    //---------------------------------------------------------
    
    /*
    * Gibt wave file header Informationen in der Console aus;
    * \param hdr: wavefile hdr
    */
    void printWaveHeaderInfos( WAVEHEADER *hdr) {
    	if(NULL == hdr) {
    		cerr << "Keine Waveheaderinformationen gefunden" << endl;
    	}
    	if(hdr->AudioFormat == 1 && hdr->SampleRate == 44100 && hdr->BitsPerSample == 16 && hdr->NumChannels ==1 )  {
    		cout << "Codec: ";
    		if (hdr->AudioFormat == 1) {
    			cout << "PCM, ";
    		}
    		else {
    			cout << "This is not a PCM file! ";
    		}
    		cout << hdr->SampleRate << " Hz, ";
    		cout << hdr->BitsPerSample << "bit, ";
    		cout << hdr->NumChannels << " channel, ";
    		cout << "Length " << ((hdr->Subchunk2Size * 8.0) / (hdr->BitsPerSample) / (hdr->NumChannels) / (hdr->SampleRate)) << " sec" << endl;
    	} else {
    		cout << "Keine Waveheaderinformationen gefunden";
    	}
    
    	// outpout
    	// codec, sampling rate, sampling precision, channels, length
    
    }
    
    /*
     * Liest den Waveheader und checkt ob das Format unterstuetzt wird;
     * \param fin: ifstream.
     * \return: NULL in case of error, waveheader else
     */
    WAVEHEADER *readWaveHeader(ifstream *fin) {
    	WAVEHEADER *hdr = NULL;
    
    	//benutze die read Funktion um binaere Daten zu lesen
    	hdr = new WAVEHEADER;
    
    	fin->read((char*)hdr, sizeof(WAVEHEADER));
    	/* TODO */
    	if (fin->eof() || fin->fail() || fin->bad()){
    		WAVEHEADER *hdr = NULL;
    	}
    
    	printWaveHeaderInfos(hdr);
    
    	return hdr;
    	delete [] hdr;
    }
    
    /*
     * Schreibt den Waveheader
     * \param fin: ifstream.
     * \param hdr: wavefile hdr
     * \return: false in case of an write error
     */
    bool writeWaveHeader(ofstream *fout, WAVEHEADER *hdr) {
    
    	if(NULL == hdr)
    		return false;
    
    	fout->write((char*)hdr, sizeof(WAVEHEADER));
    
    	if (fout->eof() || fout->fail() || fout->bad()){
    		WAVEHEADER *hdr = NULL;
    	}
    
    	// save hdr into file
    
    	return true;
    }
    
    //---------------------------------------------------------
    // Commands
    //---------------------------------------------------------
    
    /*
     * Fuer den Commando -info
     * \param fin: ifstream.
     */
    void waveFileInfo( char * filename ) {
    
    	//oeffne die Datei filename als binaere Datei (fin)
    	ifstream fin(filename, ios::in | ios::binary);
    
    	if( !fin.is_open() ) {
    		cerr << filename << " not found." << endl;	
    	} else {
    		WAVEHEADER *hdr = readWaveHeader(&fin);
    		delete hdr;
    	}
    } 
    
    void convertWaveFile( char infile[], char outfile[] )  
    {
    	cout << "Trying to convert wavefile to text:" << endl;
    
    	ifstream fin(infile, ios::in | ios::binary);
    	ofstream fout(outfile);
    
    	WAVEHEADER *hdr = NULL;
    	hdr = new WAVEHEADER;
    
    	hdr = readWaveHeader(&fin);
    
    	int samples = (hdr->Subchunk2Size * 8) / (hdr->BitsPerSample) / (hdr->NumChannels);
    	short s = samples;
    
    	for (int i= 0; i<s; i++) {
    		fin.read((char*)&s, sizeof(s));
    		fout << s <<endl;
    	}
    
    	delete [] hdr;
    
    	cout << "done" << endl;
    }
    
    void volumeWaveFile( char infile[], char outfile[], double gain )  
    {
    	cout << "Changing Volume:" << endl;
    
    	ifstream fin(infile, ios::in | ios::binary);
    	ofstream fout(outfile);
    
    	WAVEHEADER *hdr = NULL;
    	hdr = new WAVEHEADER;
    
    	hdr = readWaveHeader(&fin);
    
    	int samples = (hdr->Subchunk2Size * 8) / (hdr->BitsPerSample) / (hdr->NumChannels);
    	short s = samples;
    
    	for (int i= 0; i<s; i++) {
    		fin.read((char*)&s, sizeof(s));
    		fout << (s*gain) <<endl;
    	}
    
    	delete [] hdr;
    
    	cout << "done" << endl;
    }
    
    void mixWaveFiles( char infile1[], char infile2[], char outfile[] )  
    {
    	cout << "Mixing 2 audio files:" << endl;
    
    	ifstream fin1(infile1, ios::in | ios::binary);
    	ifstream fin2(infile2, ios::in | ios::binary);
    	ofstream fout(outfile);
    
    	WAVEHEADER *hdr1 = NULL;
    	WAVEHEADER *hdr2 = NULL;
    
    	hdr1 = new WAVEHEADER;
    	hdr2 = new WAVEHEADER;
    
    	hdr1 = readWaveHeader(&fin1);
    	hdr2 = readWaveHeader(&fin2);
    
    	int samples1 = (hdr1->Subchunk2Size * 8) / (hdr1->BitsPerSample) / (hdr1->NumChannels);
    	short s1 = samples1;
    
    	int samples2 = (hdr2->Subchunk2Size * 8) / (hdr2->BitsPerSample) / (hdr2->NumChannels);
    	short s2 = samples2;
    
    	if (s1>s2) {
    		writeWaveHeader(&fout , hdr1);
    	}
    
    	if (s1<s2) {
    		writeWaveHeader(&fout , hdr2);
    	}
    
    	if (s1>s2) {
    		for (int i= 0; i<s1; i++) {
    			fin1.read((char*)&s1, sizeof(s1));
    			fin2.read((char*)&s2, sizeof(s2));
    			fout << (s1+s2) <<endl;
    		}
    	}
    
    	if (s1<s2) {
    		for (int i= 0; i<s2; i++) {
    			fin1.read((char*)&s1, sizeof(s1));
    			fin2.read((char*)&s2, sizeof(s2));
    			fout << (s1+s2) <<endl; 
    		}
    	}
    
    	delete [] hdr1;
    	delete [] hdr2;
    
    	cout << "done" << endl;
    }
    
    void echoWaveFile( char infile[], char outfile[], double delay, double echo_gain )  
    {
    	cout << "Adding echo:" << endl;
    
    	ifstream fin(infile, ios::in | ios::binary);
    	ofstream fout(outfile);
    
    	WAVEHEADER *hdr = NULL;
    	hdr = new WAVEHEADER;
    
    	hdr = readWaveHeader(&fin);
    
    	int samples = (hdr->Subchunk2Size * 8) / (hdr->BitsPerSample) / (hdr->NumChannels);
    	short s = samples;
    
    	for (int i= 0; i<s; i++) {
    		fin.read((char*)&s, sizeof(s));
    		fout << s+((s-1)*(s-2)) <<endl;
    	}
    
    	delete [] hdr;
    
    	cout << "done" << endl;
    }
    
    //---------------------------------------------------------
    // main
    //---------------------------------------------------------
    int main(int argc, char *argv[])
    {
    	char *command = "-info";
    	char **parms = &argv[1];
    	int parms_count = argc - 1;
    
    	if(argc > 1 && argv[1][0] == '-') {
    		command = argv[1];
    		parms = &argv[2];
    		parms_count--;
    	}
    
    	// -info command standard case prints info of the given file
    	if(!strcmp(command, "-info")) {
    		if(parms_count >= 1) {
    			waveFileInfo(parms[0]);
    			return 0;
    		} else {
    			cerr << "Call " << endl;
    			cerr << argv[0] << " [-info] wavefile" << endl;
    			cerr << argv[0] << " -help : \tfor more help" << endl;
    			return 1;
    		}
    	}
    
    	// -help command
    	if(!strcmp(command, "-help")) {
    		cout << "Help:" << endl;
    		cout << argv[0] << " -totext wavfile_in  textfile_out" << endl;
    		cout << argv[0] << " -volume gain wavfile_in  wavfile_out" << endl;
    		cout << argv[0] << " -mix    wavfile1_in wavfile2_in  wavfile_out" << endl;
    		cout << argv[0] << " -echo   delay strength wavfile_in wavfile_out" << endl;
    
    		return 0;
    	}
    
    	// -totext command
    	if(!strcmp(command, "-totext")) {
    		if(parms_count >= 2) {
    			convertWaveFile( parms[0], parms[1]);
    			return 0;
    		} else {
    			cerr << "Not enough parameters" << endl;
    			return 1;
    		}
    
    	}
    
    	// -vol command
    	if(!strcmp(command, "-volume")) {
    		if(parms_count >= 3) {
    			volumeWaveFile( parms[1], parms[2], atof(parms[0]));
    			return 0;
    		} else {
    			cerr << "Not enough parameters" << endl;
    			return 1;
    		}
    
    	}
    
    	// -mix command
    	if(!strcmp(command, "-mix")) {
    		if(parms_count >= 3) {
    			mixWaveFiles( parms[0], parms[1], parms[2]);
    			return 0;
    		} else {
    			cerr << "Not enough parameters" << endl;
    			return 1;
    		}
    
    	}
    
    	// -echo command
    	if(!strcmp(command, "-echo")) {
    		if(parms_count >= 4) {
    			echoWaveFile( parms[2], parms[3], atof(parms[0]), atof(parms[1]));
    			return 0;
    		} else {
    			cerr << "Not enough parameters" << endl;
    			return 1;
    		}
    
    	}
    
    	cin.get();
    	cin.get();
    	return 0;
    }
    

    Kompilieren tut es schonmal ohne Probleme. Doch ich kann einfach keine Eingaben tätigen um Audiofiles (.WAV) zu manipulieren, da sich die cmd sofort schliesst.
    Ich habe schon versucht zu Debuggen und herausgefunden, dass der Fehler irgendwo bei der Funktion "WAVEHEADER *readWaveHeader(ifstream *fin) {...}" ist.
    Sieht vielleicht Jemand was ich falsch mache in der Funktion?

    Gruss Hans


  • Mod

    Kompilieren ohne Probleme? Ich denke nein:

    test.cc: In function ‘WAVEHEADER* readWaveHeader(std::ifstream*)’:
    test.cc:84: warning: unused variable ‘hdr’
    test.cc: In function ‘bool writeWaveHeader(std::ofstream*, WAVEHEADER*)’:
    test.cc:107: warning: unused variable ‘hdr’
    test.cc: At global scope:
    test.cc:245: warning: unused parameter ‘delay’
    test.cc:245: warning: unused parameter ‘echo_gain’
    test.cc: In function ‘int main(int, char**)’:
    test.cc:275: warning: deprecated conversion from string constant to ‘char*’
    

    Außerdem:
    - Nutz mal Referenzen
    - Nutz mal Vectoren

    Nur mal ein Beispiel:

    WAVEHEADER *readWaveHeader(ifstream *fin) {
        WAVEHEADER *hdr = NULL;
    
        //benutze die read Funktion um binaere Daten zu lesen
        hdr = new WAVEHEADER;
    
        fin->read((char*)hdr, sizeof(WAVEHEADER));
        /* TODO */
        if (fin->eof() || fin->fail() || fin->bad()){
            WAVEHEADER *hdr = NULL;
        }
    
        printWaveHeaderInfos(hdr);
    
        return hdr;
        delete [] hdr;
    }
    

    Hier ist jede Zeile mindestens gefährlich, die meisten schlichtweg falsch:
    -Per Pointer Objekte rausgeben, sehr ungewöhnlich und fehleranfällig
    -Per Pointer Objekte annehmen, sehr ungewöhnlich und fehleranfällig
    -Unsinniges Nullsetzen
    -C-Casts sollten immer Alarmzeichen sein, da sie dem reinterpret_cast aus C++ entsprechen können. Siehe dazu die Bemerkung von cooky451 unter mir.
    -Aus obigem Grund solltest du C-Casts auch vermeiden, da sie unauffällig aussehen, dem Compiler aber sehr klar sagen, dass er die Schnauze halten soll, selbst wenn es wahrscheinlich falsch ist. Vermutlich hast du so noch mehr potentiell nützliche Warnungen unterdrückt. Nimm die C++-Casts, da sieht man, was passiert. Wenn du sagst, das wäre viel Schreibarbeit, dann ist dein Design kaputt, weil du zu viel casten musst.
    -Guck mal, was if (fin) wohl macht
    -Guck auch mal, was fail, bad und eof genau machen und ob deine Abfrage nicht redundant ist
    -Du legst da eine neue lokale Variable im if-Block an, die nichts mit dem hdr außenrum zu tun hat.
    -delete[] passt nicht zum new
    -delete[] wird nie erreicht
    -würde delete[] erreicht, würdest du ein ungültiges Objekt zurück geben

    Wenn in einer Funktion schon so viel falsch ist, mache ich nicht weiter. Du spielst hier mit Sachen rum (manuelle Speicherverwaltung), die sehr gefährlich sind und du weißt nicht, was du überhaupt tust. Kein Wunder, dass das nicht funktioniert. Fragt sich nur, warum du das tust, du hast das gar nicht nötig.

    edit: Der Intel Compiler ist oftmals noch pingeliger als der GCC:

    test.cc(84): remark #1599: declaration hides variable "hdr" (declared at line 76)
              WAVEHEADER *hdr = NULL;
                          ^
    
    test.cc(84): remark #177: variable "hdr" was declared but never referenced
              WAVEHEADER *hdr = NULL;
                          ^
    
    test.cc(90): remark #111: statement is unreachable
          delete [] hdr;
          ^
    
    test.cc(107): remark #1599: declaration hides parameter "hdr" (declared at line 99)
              WAVEHEADER *hdr = NULL;
                          ^
    
    test.cc(107): remark #177: variable "hdr" was declared but never referenced
              WAVEHEADER *hdr = NULL;
                          ^
    
    test.cc(152): remark #2259: non-pointer conversion from "int" to "short" may lose significant bits
          short s = samples;
                    ^
    
    test.cc(179): remark #2259: non-pointer conversion from "int" to "short" may lose significant bits
          short s = samples;
                    ^
    
    test.cc(209): remark #2259: non-pointer conversion from "int" to "short" may lose significant bits
          short s1 = samples1;
                     ^
    
    test.cc(212): remark #2259: non-pointer conversion from "int" to "short" may lose significant bits
          short s2 = samples2;
                     ^
    
    test.cc(258): remark #2259: non-pointer conversion from "int" to "short" may lose significant bits
          short s = samples;
                    ^
    
    test.cc(245): remark #869: parameter "delay" was never referenced
      void echoWaveFile( char infile[], char outfile[], double delay, double echo_gain )  
                                                               ^
    
    test.cc(245): remark #869: parameter "echo_gain" was never referenced
      void echoWaveFile( char infile[], char outfile[], double delay, double echo_gain )  
                                                                             ^
    

    Der findet also noch mehr technische Fehler, die ich oben erst als Zusatzkommentare zu deiner Funktion geschrieben habe 👍 .



  • Du verlässt dich irgendwie darauf, dass die Member des struct im Speicher direkt hintereinanderliegen, das ist aber nicht garantiert!
    Zudem solltest du dich mal entscheiden, ob du C++ oder C schreiben willst, das da ist offen gesagt ziemlich.. hässlich. (z.B. solltest du dir mal überlegen was Zeile 90 macht. :D)

    Wenn du den Debugger bereits kennst, guck doch einfach in welcher Zeile sich dein Programm beendet? Ich verstehe dein Problem nicht?

    Edit:
    Autsch. Da war ich mal langsamer..



  • So, habe es nocheinmal überarbeitet, hoffe konnte alles beheben.
    Muss mir auch mal den Intel Compiler runterladen.

    [code]
    /********************************************************************
    	purpose:	A simple PCM Wave File Editing TOOL
    
    	created:	2010/11/08
    	filename: 	audio_tmpl.cpp
    	author:		
    
    *********************************************************************/
    
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <cstring>
    #include <limits.h>
    #include <stdlib.h>
    
    using namespace std;
    
    struct WAVEHEADER {
    	char	ChunkID[4];	//          Contains the letters "RIFF" in ASCII form
    	int		ChunkSize;
    	int		Format;
    	char	Subchunk1ID[4];
    	int		Subchunk1Size;
    	short	AudioFormat;
    	short	NumChannels;
    	int		SampleRate;
    	int		ByteRate;
    	short	BlockAlign;
    	short	BitsPerSample;
    	char	Subchunk2ID[4];
    	int		Subchunk2Size;
    };
    
    //---------------------------------------------------------
    // helper functions
    //---------------------------------------------------------
    
    /*
    * Gibt wave file header Informationen in der Console aus;
    * \param hdr: wavefile hdr
    */
    void printWaveHeaderInfos( WAVEHEADER *hdr) {
    	if(NULL == hdr) {
    		cerr << "Keine Waveheaderinformationen gefunden" << endl;
    	}
    	if(hdr->AudioFormat == 1 && hdr->SampleRate == 44100 && hdr->BitsPerSample == 16 && hdr->NumChannels ==1 )  {
    		cout << "Codec: ";
    		if (hdr->AudioFormat == 1) {
    			cout << "PCM, ";
    		}
    		else {
    			cout << "This is not a PCM file! ";
    		}
    		cout << hdr->SampleRate << " Hz, ";
    		cout << hdr->BitsPerSample << "bit, ";
    		cout << hdr->NumChannels << " channel, ";
    		cout << "Length " << ((hdr->Subchunk2Size * 8.0) / (hdr->BitsPerSample) / (hdr->NumChannels) / (hdr->SampleRate)) << " sec" << endl;
    	} else {
    		cout << "Keine Waveheaderinformationen gefunden";
    	}
    
    	// outpout
    	// codec, sampling rate, sampling precision, channels, length
    
    }
    
    /*
     * Liest den Waveheader und checkt ob das Format unterstuetzt wird;
     * \param fin: ifstream.
     * \return: NULL in case of error, waveheader else
     */
    WAVEHEADER *readWaveHeader(ifstream *fin) {
    	WAVEHEADER *hdr = NULL;
    
    	//benutze die read Funktion um binaere Daten zu lesen
    	hdr = new WAVEHEADER;
    
    	fin->read((char*)hdr, sizeof(WAVEHEADER));
    	/* TODO */
    	if (fin->eof() || fin->fail() || fin->bad()){
    		cout << "Fehler beim Ausgeben des Files";
    	}
    
    	printWaveHeaderInfos(hdr);
    
    	return hdr;
    }
    
    /*
     * Schreibt den Waveheader
     * \param fin: ifstream.
     * \param hdr: wavefile hdr
     * \return: false in case of an write error
     */
    bool writeWaveHeader(ofstream *fout, WAVEHEADER *hdr) {
    
    	if(NULL == hdr) {
    		return false;
    	}
    
    	fout->write((char*)hdr, sizeof(WAVEHEADER));
    
    	if (fout->eof() || fout->fail() || fout->bad()){
    		cout << "Fehler beim Ausgeben des Files";
    	}
    
    	// save hdr into file
    
    	return true;
    }
    
    //---------------------------------------------------------
    // Commands
    //---------------------------------------------------------
    
    /*
     * Fuer den Commando -info
     * \param fin: ifstream.
     */
    void waveFileInfo( char * filename ) {
    
    	//oeffne die Datei filename als binaere Datei (fin)
    	ifstream fin(filename, ios::in | ios::binary);
    
    	if( !fin.is_open() ) {
    		cerr << filename << " not found." << endl;	
    	} else {
    		WAVEHEADER *hdr = readWaveHeader(&fin);
    		delete hdr;
    	}
    } 
    
    void convertWaveFile( char infile[], char outfile[] )  
    {
    	cout << "Trying to convert wavefile to text:" << endl;
    
    	ifstream fin(infile, ios::in | ios::binary);
    	ofstream fout(outfile);
    
    	WAVEHEADER *hdr = readWaveHeader(&fin);
    
    	short samples = (hdr->Subchunk2Size * 8) / (hdr->BitsPerSample) / (hdr->NumChannels);
    	short s = samples;
    
    	for (int i= 0; i<s; i++) {
    		fin.read((char*)&s, sizeof(s));
    		fout << s <<endl;
    	}
    
    	delete [] hdr;
    
    	cout << "done" << endl;
    }
    
    void volumeWaveFile( char infile[], char outfile[], double gain )  
    {
    	cout << "Changing Volume:" << endl;
    
    	ifstream fin(infile, ios::in | ios::binary);
    	ofstream fout(outfile);
    
    	WAVEHEADER *hdr = readWaveHeader(&fin);
    
    	short samples = (hdr->Subchunk2Size * 8) / (hdr->BitsPerSample) / (hdr->NumChannels);
    	short s = samples;
    
    	for (int i= 0; i<s; i++) {
    		fin.read((char*)&s, sizeof(s));
    		fout << (s*gain) <<endl;
    	}
    
    	delete [] hdr;
    
    	cout << "done" << endl;
    }
    
    void mixWaveFiles( char infile1[], char infile2[], char outfile[] )  
    {
    	cout << "Mixing 2 audio files:" << endl;
    
    	ifstream fin1(infile1, ios::in | ios::binary);
    	ifstream fin2(infile2, ios::in | ios::binary);
    	ofstream fout(outfile);
    
    	WAVEHEADER *hdr1 = readWaveHeader(&fin1);
    	WAVEHEADER *hdr2 = readWaveHeader(&fin2);
    
    	short samples1 = (hdr1->Subchunk2Size * 8) / (hdr1->BitsPerSample) / (hdr1->NumChannels);
    	short s1 = samples1;
    
    	short samples2 = (hdr2->Subchunk2Size * 8) / (hdr2->BitsPerSample) / (hdr2->NumChannels);
    	short s2 = samples2;
    
    	if (s1>s2) {
    		writeWaveHeader(&fout , hdr1);
    	}
    
    	if (s1<s2) {
    		writeWaveHeader(&fout , hdr2);
    	}
    
    	if (s1>s2) {
    		for (int i= 0; i<s1; i++) {
    			fin1.read((char*)&s1, sizeof(s1));
    			fin2.read((char*)&s2, sizeof(s2));
    			fout << (s1+s2) <<endl;
    		}
    	}
    
    	if (s1<s2) {
    		for (int i= 0; i<s2; i++) {
    			fin1.read((char*)&s1, sizeof(s1));
    			fin2.read((char*)&s2, sizeof(s2));
    			fout << (s1+s2) <<endl; 
    		}
    	}
    
    	delete [] hdr1;
    	delete [] hdr2;
    
    	cout << "done" << endl;
    }
    
    void echoWaveFile( char infile[], char outfile[], double delay, double echo_gain )  
    {
    	cout << "Adding echo:" << endl;
    
    	ifstream fin(infile, ios::in | ios::binary);
    	ofstream fout(outfile);
    
    	WAVEHEADER *hdr = readWaveHeader(&fin);
    
    	short samples = (hdr->Subchunk2Size * 8) / (hdr->BitsPerSample) / (hdr->NumChannels);
    	short s = samples;
    
    	for (int i= 0; i<s; i++) {
    		fin.read((char*)&s, sizeof(s));
    		fout << s*(delay*echo_gain) <<endl;
    	}
    
    	delete [] hdr;
    
    	cout << "done" << endl;
    }
    
    //---------------------------------------------------------
    // main
    //---------------------------------------------------------
    int main(int argc, char *argv[])
    {
    	char *command = "-info";
    	char **parms = &argv[1];
    	int parms_count = argc - 1;
    
    	if(argc > 1 && argv[1][0] == '-') {
    		command = argv[1];
    		parms = &argv[2];
    		parms_count--;
    	}
    
    	// -info command standard case prints info of the given file
    	if(!strcmp(command, "-info")) {
    		if(parms_count >= 1) {
    			waveFileInfo(parms[0]);
    			return 0;
    		} else {
    			cerr << "Call " << endl;
    			cerr << argv[0] << " [-info] wavefile" << endl;
    			cerr << argv[0] << " -help : \tfor more help" << endl;
    			return 1;
    		}
    	}
    
    	// -help command
    	if(!strcmp(command, "-help")) {
    		cout << "Help:" << endl;
    		cout << argv[0] << " -totext wavfile_in  textfile_out" << endl;
    		cout << argv[0] << " -volume gain wavfile_in  wavfile_out" << endl;
    		cout << argv[0] << " -mix    wavfile1_in wavfile2_in  wavfile_out" << endl;
    		cout << argv[0] << " -echo   delay strength wavfile_in wavfile_out" << endl;
    
    		return 0;
    	}
    
    	// -totext command
    	if(!strcmp(command, "-totext")) {
    		if(parms_count >= 2) {
    			convertWaveFile( parms[0], parms[1]);
    			return 0;
    		} else {
    			cerr << "Not enough parameters" << endl;
    			return 1;
    		}
    
    	}
    
    	// -vol command
    	if(!strcmp(command, "-volume")) {
    		if(parms_count >= 3) {
    			volumeWaveFile( parms[1], parms[2], atof(parms[0]));
    			return 0;
    		} else {
    			cerr << "Not enough parameters" << endl;
    			return 1;
    		}
    
    	}
    
    	// -mix command
    	if(!strcmp(command, "-mix")) {
    		if(parms_count >= 3) {
    			mixWaveFiles( parms[0], parms[1], parms[2]);
    			return 0;
    		} else {
    			cerr << "Not enough parameters" << endl;
    			return 1;
    		}
    
    	}
    
    	// -echo command
    	if(!strcmp(command, "-echo")) {
    		if(parms_count >= 4) {
    			echoWaveFile( parms[2], parms[3], atof(parms[0]), atof(parms[1]));
    			return 0;
    		} else {
    			cerr << "Not enough parameters" << endl;
    			return 1;
    		}
    
    	}
    
    	cin.get();
    	cin.get();
    	return 0;
    }
    


  • Du hast zwar einige Kritikpunkte behoben, aber die wesentlichen Bemängelungen sind immer noch drin, zum Beispiel:

    WAVEHEADER *readWaveHeader(ifstream *fin)
    

    Es besteht kein Grund, hier Zeiger zu benutzen, weder für den Rückgabewert noch für den Parameter. Gib´ ein Objekt als Value zurück und übergib´ den Inputstream als Referenz:

    WAVEHEADER readWaveHeader( ifstream& ifs )
    {
       WAVEHEADER wh;
    
       // Daten lesen
    
       // Objekt zurückgeben
       return wh;
    }
    

    Wenn du das Ganze noch C++ konform lösen willst solltest du den operator>> und oeprator<< für WAVEHEADER und istream/ostream überladen:

    istream& operator>>( istream& is, const WAVEHEADER& wh )
    {
       // Daten aus stream lesen
    }
    
    ostream& opertaor<<( ostream& os, WAVEHEADER& wh )
    {
       // Daten in stream schreiben
    }
    

    Außerdem hat cooky451 schon erwähnt, dass die Elemente einer Struktur/Klasse nicht lückenlos linear hintereinander im Speicher liegen müssen. Der Compiler kann zwischen einzelnen Elementen Füllbytes (Padding) einfügen, um schneller auf die Elemente zugreifen zu können. Daher solltest du dem Compiler noch explizit sagen, dass er für die Struktur kein Padding verwenden darf. Wie das geht hängt vom Compiler ab. Beim Codegear 2007 könnte das so aussehen:

    #pragma pack( push, 1 ) // Elemente auf Bytegrenzen ausrichten
    struct WAVEHEADER
    {
       ...
    };
    #pragma pack( pop ) // alte Ausrichtung wiederherstellen
    

    PS:
    Die Ausrichtung für die Struktur muss natürlich nur dann auf Bytegrenzen gesetztz werden, wenn du sie am Stück mit write schreiben oder mit read willst. Alternativ kannst du auch alle Elemente separat in den Stream schreiben (bzw. aus ihm lesen), dann ist die Elementausrichtung der Struktur egal.

    PPS:
    Es gibt den Datentyp std::string , dann brauchst du keine char-Arrays mehr durch die Gegend zu reichen.


Anmelden zum Antworten