Wczytywanie pliku wav do tablicy c++

0

Czy jest możliwość wczytania pliku dźwiękowego w formacie wav w taki sposób żeby każdy kanał był w osobnej tablicy. Jeżeli tak to w jaki sposób można to zrobić?
Z góry dziękuję za pomoc :)

1

Jak najbardziej można, zapoznaj się ze specyfikacją formatu http://soundfile.sapp.org/doc/WaveFormat/ i przetraw sobie ten plik odpowiednio.

2

ja dodam, że pomiędzy fmt a data mogą się znajdować inne “chunki”, które trzeba przeskoczyć.

długość chunka jest zawsze parzysta: jeśli w polu długości jest liczba nieparzysta, trzeba „zakrąglić w górę” do parzystej; na końcu wtedy jest jeden nieużywany bajt.
https://en.wikipedia.org/wiki/Resource_Interchange_File_Format

poza tym trzeba sprawdzić wartości w fmt, czy jesteśmy w stanie przetrawić dany plik. konkretnie czy AudioFormat jest równe 1, i stosować się do wartości podanych w NumChannels, SampleRate, BlockAlign itd.

0

Zrobiłem odczytywanie nagłówka wave. Teraz nie wiem jak czytać kanały do tablicy. Mam to czytać po 4 bajty w pętli czy jak?

 

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

int main()
{
 //odczyt nagłówka wave
    typedef unsigned int UINT;
    FILE* fp = fopen("bird2.wav","r");
    if(!fp)
    {
        perror ("ERROR");
    }
    else
    {
        char type[5];
        type[4]='\0';
        unsigned int size,chunkSize,sampleRate,avgBytesPerSec,dataSize=0;
        short formatType,channels,bytesPerSample,bitesPerSample=0;

        fread(type,sizeof(char),4,fp);
        if(memcmp(type,"RIFF",4)!=0)
        {
            perror ("ERROR");
        }
        else
        {
            fread(&size,sizeof(unsigned int),1,fp);

            fread(type,sizeof(char),4,fp);
            if(memcmp(type,"WAVE",4)!=0)
            {
                perror ("ERROR");

            }
            else
            {
                fread(type,sizeof(char),4,fp);
                fread(&chunkSize,sizeof(UINT),1,fp);
                fread(&formatType,sizeof(short),1,fp);          //1 = PCM
                fread(&channels,sizeof(short),1,fp);
                fread(&sampleRate,sizeof(UINT),1,fp);
                fread(&avgBytesPerSec,sizeof(UINT),1,fp);
                fread(&bytesPerSample,sizeof(short),1,fp);
                fread(&bitesPerSample,sizeof(short),1,fp);

                fread(type,sizeof(char),4,fp);
                if(memcmp(type,"data",4)!=0)
                {
                    perror ("ERROR");
                }
                else
                {
                    fread(&dataSize,sizeof(unsigned int),1,fp);

                }
            }
        }
    }
}
0

fread(type,sizeof(char),4,fp);
fread(&chunkSize,sizeof(UINT),1,fp);

Nagłówek może mieć różną długość, właśnie ją odczytałeś, ale nie dopilnowujesz by przeczytać tyle ile w pliku podano (z zaokrągleniem w górę do parzystej).

fread(type,sizeof(char),4,fp);
if(memcmp(type,"data",4)!=0)

Jak już wspominałem, przed data mogą być inne “chunki”. Więc jeśli trafiłeś na coś innego niż data, należy odczytać rozmiar, przeskoczyć, i zobaczyć czy następny to nie data. I do skutku (a raczej do końca chunka RIFF).

fread(&formatType,sizeof(short),1,fp); //1 = PCM

Fajnie, tylko przydałoby się sprawdzić to PCM.

Mam to czytać po 4 bajty w pętli czy jak?

Nie cztery, tylko BlockAlign bajtów.

Poza tym sprawdź ile jest kanałów. nie zawsze są dwa. może być jeden (mono), a może być np. sześć (5.1). Bitów na sampel też nie musi być 16, może być 8 albo 24. Możesz oczywiście olać obsługę 8-bitowych plików 5.1 (to byłoby niezłe WTF, ale możliwe), ale mimo wszystko sprawdzaj czy plik jest zjadliwy, bo lepiej wyświetlić błąd niż śmieci (albo wywalić program, a już w ogóle niewybaczalne jest puścić jakieś śmieci w złym formacie na głośniki).

W standardowym 16-bitowym PCM stereo będziesz miał cztery bajty - dwie liczby short, jedna na lewy kanał druga na prawy (nie pamiętam kolejności).

Tu masz przykład rzeczywistego nagłówka pliku WAV. twój program powinien takie coś być w stanei przemielić i znaleźć dane, nawet jeśli akurat 5.1 cię nie interesuje:
http://www.jensign.com/multichannel/multichannelformat.html

I pamiętaj że na końcu pliku też mogą być dodatkowe rzeczy. Dlatego nie czytaj danych do końca pliku, a tylko tyle, ile masz wskazane w rozmiarze chunka data.

EDIT: wyczytałem że formatType równe 1 dopuszcza tylko jeden albo dwa kanały i max 16 bitów. Więcej kanałów wymaga innej wartości, nawet jeśli to jest PCM. Więc zacznij od sprawdzenia tego pola.
Wtedy też nagłówek (fmt) jest krótki, bez dodatkowych pól na końcu. Ale i tak bym - dla zasady - przestrzegał podanego rozmiaru chunka.

0

Ja używam do tego biblioteki bass.
http://pastebin.com/UH1FQGwu
Dokładniej zainteresuj się funkcją UpdateSpectrum z przykładu, a jeszcze dokładniej BASS_ChannelGetData().

1

Temat czytania plików WAV był wielokrotnie poruszany. Tu masz kod poprawnie czytający ten format -> http://4programmers.net/Forum/1113605

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