WAVE odczyt i zapis.

Odpowiedz Nowy wątek
2017-11-14 19:41
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");
}
 

Pozostało 580 znaków

2017-11-15 10:30

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/Forum/C_i_C++/247347-odczyt_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ł).

Pozostało 580 znaków

2017-11-15 22:34
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");
}

Pozostało 580 znaków

2017-11-15 23:32
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.

edytowany 2x, ostatnio: Azarien, 2017-11-15 23:33
Kwestia gustu z tym castem, ja też się przychylam do wersji brzydszej, dla mnie jest czytelniejsza. - alagner wczoraj, 09:06
w jednej linijce może tak, ale jak ci się nakłada to outFile.write(reinterpret_cast<char*> w 10 liniach pod rząd to właściwa treść (nazwa pola) ginie w gąszczu pustosłowia. - Azarien wczoraj, 09:11

Pozostało 580 znaków

wczoraj, 10:25
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.

Pozostało 580 znaków

wczoraj, 12:01
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.

Pozostało 580 znaków

wczoraj, 12:08
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.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
WAVE jest w little endianie - to windowsowy format. - _0x666_ wczoraj, 12:30
Zgodnie z dokumentacją to WAVE ma mieszaną endianę. Wspomniałem o endianie bo trzeba o tym pamięć, gdy się wczytuje dane binarne. - MarekR22 wczoraj, 12:56

Pozostało 580 znaków

wczoraj, 12:35
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

edytowany 1x, ostatnio: Azarien, wczoraj, 12:36

Pozostało 580 znaków

wczoraj, 13:27
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.

edytowany 1x, ostatnio: _0x666_, wczoraj, 13:30

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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