WAVE odczyt i zapis.

0

Witam.
Mam problem natury takiej, że gdy wczytuję plik .wav i później chcę go zapisać w takiej samej postaci to plik wyjściowy ma 44b no i niestety nie działa.
Nie jestem pewien czy po subchunk2Size nie ma jakichś danych lub czy pomiędzy coś nie pominąłem.
Pozdrawiam.

#include <iostream>
#include <fstream>

using namespace std;

struct wavHEADER
{
public :
    //wavHEADER() : Data(nullptr) {}
    //~wavHEADER() { delete[] Data; }
    char riff[4];
    int chunkSize;
    char wave[4];
    char fmt[4];
    int subchunk1Size;
    short int audioFormat;
    short int numChannels;

    int sampleRate;
    int ByteRate;
    short int BlockAlign;
    short int BitsPerSample;

    char SubChunk2ID[4];
    int subchunk2Size;
    //byte* Data;
};

//stałe
static const uint32_t size_ui32 = sizeof(uint32_t);
static const uint32_t size_ui16 = sizeof(uint16_t);

int main()
{
    //wczytanie pliku
    ifstream file("input.wav",ios::in | ios::binary); 
    wavHEADER wavFile;

    if (file.good()) {
        file.read(wavFile.riff, 4);
        file.read(reinterpret_cast<char*>(&wavFile.chunkSize), size_ui32);
        file.read(wavFile.wave, 4);
        file.read(wavFile.fmt, 4);
        file.read(reinterpret_cast<char*>(&wavFile.subchunk1Size), size_ui32);
        file.read(reinterpret_cast<char*>(&wavFile.audioFormat), size_ui16);
        file.read(reinterpret_cast<char*>(&wavFile.numChannels), size_ui16);
        file.read(reinterpret_cast<char*>(&wavFile.sampleRate), size_ui32);
        file.read(reinterpret_cast<char*>(&wavFile.ByteRate), size_ui32);
        file.read(reinterpret_cast<char*>(&wavFile.BlockAlign), size_ui16);
        file.read(reinterpret_cast<char*>(&wavFile.BitsPerSample), size_ui16);
        file.read(wavFile.SubChunk2ID, 4);
        file.read(reinterpret_cast<char*>(&wavFile.subchunk2Size), size_ui32);
        //wavFile.data = new byte[wavFile.subchunk2Size];
        //file.read(reinterpret_cast<char*>(wavFile.data), sizeof(wavFile.subchunk2Size));
        file.close();
    }

    cout << "RIFF: " << wavFile.riff[0] << wavFile.riff[1] << wavFile.riff[2] << wavFile.riff[3] << endl;
    cout << "chunkSize: " << wavFile.chunkSize << endl;
    cout << "wave: " << wavFile.wave[0] << wavFile.wave[1] << wavFile.wave[2] << wavFile.wave[3] << endl;
    cout << "fmt: " << wavFile.fmt[0] << wavFile.fmt[1] << wavFile.fmt[2] << wavFile.fmt[3] << endl;
    cout << "subchunk1Size: " << wavFile.subchunk1Size << endl;
    cout << "audioFormat: " << wavFile.audioFormat << endl;
    cout << "numChannels: " << wavFile.numChannels << endl;
    cout << "sampleRate: " << wavFile.sampleRate << endl;
    cout << "ByteRate: " << wavFile.ByteRate << endl;
    cout << "BlockAlign: " << wavFile.BlockAlign << endl;
    cout << "BitsPerSample: " << wavFile.BitsPerSample << endl;
    cout << "data: " << wavFile.SubChunk2ID[0] << wavFile.SubChunk2ID[1] << wavFile.SubChunk2ID[2] << wavFile.SubChunk2ID[3] << endl;
    cout << "subchunk2Size: " << wavFile.subchunk2Size << endl;

    //zapisanie do pliku
    ofstream file2("output.wav", ios::binary | ios::app | ios::ate);
    if (file2.good())
    {
        file2.write(wavFile.riff, 4);
        file2.write(reinterpret_cast<char*>(&wavFile.chunkSize), size_ui32);
        file2.write(wavFile.wave, 4);
        file2.write(wavFile.fmt, 4);
        file2.write(reinterpret_cast<char*>(&wavFile.subchunk1Size), size_ui32);
        file2.write(reinterpret_cast<char*>(&wavFile.audioFormat), size_ui16);
        file2.write(reinterpret_cast<char*>(&wavFile.numChannels), size_ui16);
        file2.write(reinterpret_cast<char*>(&wavFile.sampleRate), size_ui32);
        file2.write(reinterpret_cast<char*>(&wavFile.ByteRate), size_ui32);
        file2.write(reinterpret_cast<char*>(&wavFile.BlockAlign), size_ui16);
        file2.write(reinterpret_cast<char*>(&wavFile.BitsPerSample), size_ui16);
        file2.write(wavFile.SubChunk2ID, 4);
        file2.write(reinterpret_cast<char*>(&wavFile.subchunk2Size), size_ui32);
        //wavFile.data = new byte[wavFile.subchunk2Size];
        //file.read(reinterpret_cast<char*>(wavFile.data), sizeof(wavFile.subchunk2Size));
        file.close();
    }

    system("pause");
}
1

i później chcę go zapisać w takiej samej postaci to plik wyjściowy ma 44b

No a ile ma mieć, jeśli nie zapisujesz nic więcej poza nagłówkiem?

https://4programmers.net/Foru[...]dczyt_wav?p=1113605#id1113605 <--- tu masz przykład kodu czytającego (poprawnie) pliki .wav (między blokiem 'fmt ' a 'data' mogą występować inne bloki. Twój kod to ignoruje i czyta na rympał).

0

@_0x666_: wiem, że ignoruje to, robię to specjalnie na razie, ale na razie działam na jednym pliku i jakoś to idzie ponieważ to sprawdzam cout'em.
Mam jeszcze pytanie, gdybym chciał wyświetlić zawartość wavFile.data powiedzmy w postaci binarnej (nie całą oczywiście, jakiś kawałek) to czym powinienem się zainteresować?
Myślałem, że tym sposobem to nie zadziała, ale jednak się udało:

#include <iostream>
#include <fstream>

using namespace std;

struct wavHEADER
{
public :
    char riff[4];
    int chunkSize;
    char wave[4];
    char fmt[4];
    int subchunk1Size;
    short int audioFormat;
    short int numChannels;

    int sampleRate;
    int ByteRate;
    short int BlockAlign;
    short int BitsPerSample;

    char SubChunk2ID[4];
    int subchunk2Size;
    char* data;
};

//stałe
static const uint32_t size_ui32 = sizeof(uint32_t);
static const uint32_t size_ui16 = sizeof(uint16_t);

int main()
{
    //wczytanie pliku
    ifstream inFile("input.wav",ios::in | ios::binary); 
    wavHEADER wavFile;

    if (inFile.good()) {
        inFile.read(wavFile.riff, 4);
        inFile.read(reinterpret_cast<char*>(&wavFile.chunkSize), size_ui32);
        inFile.read(wavFile.wave, 4);
        inFile.read(wavFile.fmt, 4);
        inFile.read(reinterpret_cast<char*>(&wavFile.subchunk1Size), size_ui32);
        inFile.read(reinterpret_cast<char*>(&wavFile.audioFormat), size_ui16);
        inFile.read(reinterpret_cast<char*>(&wavFile.numChannels), size_ui16);
        inFile.read(reinterpret_cast<char*>(&wavFile.sampleRate), size_ui32);
        inFile.read(reinterpret_cast<char*>(&wavFile.ByteRate), size_ui32);
        inFile.read(reinterpret_cast<char*>(&wavFile.BlockAlign), size_ui16);
        inFile.read(reinterpret_cast<char*>(&wavFile.BitsPerSample), size_ui16);
        inFile.read(wavFile.SubChunk2ID, 4);
        inFile.read(reinterpret_cast<char*>(&wavFile.subchunk2Size), size_ui32);
        wavFile.data = new char[wavFile.subchunk2Size];                                 //data
        inFile.read(wavFile.data, wavFile.subchunk2Size);                              //data
        inFile.close();
    }

    //zapisanie do pliku
    ofstream outFile("output.wav", ios::binary | ios::app);
    if (outFile.good())
    {
        outFile.write(wavFile.riff, 4);
        outFile.write(reinterpret_cast<char*>(&wavFile.chunkSize), size_ui32);
        outFile.write(wavFile.wave, 4);
        outFile.write(wavFile.fmt, 4);
        outFile.write(reinterpret_cast<char*>(&wavFile.subchunk1Size), size_ui32);
        outFile.write(reinterpret_cast<char*>(&wavFile.audioFormat), size_ui16);
        outFile.write(reinterpret_cast<char*>(&wavFile.numChannels), size_ui16);
        outFile.write(reinterpret_cast<char*>(&wavFile.sampleRate), size_ui32);
        outFile.write(reinterpret_cast<char*>(&wavFile.ByteRate), size_ui32);
        outFile.write(reinterpret_cast<char*>(&wavFile.BlockAlign), size_ui16);
        outFile.write(reinterpret_cast<char*>(&wavFile.BitsPerSample), size_ui16);
        outFile.write(wavFile.SubChunk2ID, 4);
        outFile.write(reinterpret_cast<char*>(&wavFile.subchunk2Size), size_ui32);
        outFile.write(wavFile.data, wavFile.subchunk2Size);
        outFile.close();
    }
    system("pause");
}
1
static const uint32_t size_ui32 = sizeof(uint32_t);

inFile.read(reinterpret_cast<char*>(&wavFile.chunkSize), size_ui32);

Rozwlekle to piszesz. Nieczytelnie. Co jest złego w:

inFile.read((char*)&wavFile.chunkSize, 4);

skoro chunkSize ma z definicji cztery bajty.
Poza tym jest raczej liczbą bez znaku. W strukturze natomiast masz inta. Ale sajzof pobierasz z uint32_t. To już w ogóle dziwnie.

1

(...) gdybym chciał wyświetlić zawartość wavFile.data powiedzmy w postaci binarnej

Na pewno binarnej? :|

Popraw typy w wavHEADER. Żadne tam inty i shorty, tylko uint32_t i uint16_t.

0

@_0x666_: tak, będę chciał wykorzystać to w steganografii i zmienić najmniej znaczące bity. Dlatego chciałbym mieć to zapisane w systemie dwójkowym.
Czy dobrze to rozumiem, wavFile.data jest typu char więc jak zrobię bitset<8> wavFile.data[0] to dostanę ciąg bitów składający się na ten bajt tak ?
Wszystko o czym mówiliście wezmę pod uwagę gdy tylko przysiądę przy tym.

0

IMO najlepiej zdefiniować szablon funkcji pomocniczej i wszytko od razu będzie czytelniejsze:

template<class T>
istream& LoadBigEndian(istream& input, T& value)
{
     T tmp;
     input.read(reinterpret_cast<char*>(&tmp), sizeof(T));
     value = FromBigEndian(tmp);
     return input;
}

Ten szablon można udoskonalić, chodzi mi o sam koncept.

1

W WinAPI masz gotową strukturę WAVEFORMATEX którą wypełniasz i zapisujesz do pliku za jednym zamachem.

https://msdn.microsoft.com/en-us/library/dd757713(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/dd757676(v=vs.85).aspx

1

(...) więc jak zrobię bitset<8> wavFile.data[0] to dostanę ciąg bitów składający się na ten bajt tak ?

Jeśli masz na myśli bitset<8>(wavFile.data[0]), to tak.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0