Odczyt .wav

0

Witam, cos nie moge odtworzyc .wav
Co robie nie tak ;< ?

FILE  *wavFile;
              wavFile = fopen(FileDialog1->GetPath(), "rb");   
              if( wavFile == NULL )
              {
              
              }
              else
              {



                typedef struct  WAV_HEADER{
    char                RIFF[4];       
    unsigned long       ChunkSize;      
    char                WAVE[4];        
    char                fmt[4];        
    unsigned long       Subchunk1Size; 
    unsigned short      AudioFormat;    
    unsigned short      NumOfChan;      
    unsigned long       SamplesPerSec;  
    unsigned long       BytesPerSec;    
    unsigned short      BlockAlign;    
    unsigned short      BitsPerSample;  
    char                Subchunk2ID[4]; 
    unsigned long       Subchunk2Size;  

                                            }wav_hdr;

                    wav_hdr wavHeader;
                    int headerSize = sizeof(wav_hdr),filelength = 0;
                    fread(&wavHeader,headerSize,1,wavFile);
                    fclose(wavFile);


SAMPLE_RATE = wavHeader.SamplesPerSec;
NUM_CHANNELS = wavHeader.NumOfChan; 

data.frameIndex = 0;
numSamples = ((8 * wavHeader.Subchunk2Size)/wavHeader.BitsPerSample  );
totalFrames = (numSamples / NUM_CHANNELS);
NUM_SECONDS = (totalFrames / SAMPLE_RATE);


fread( data.recordedSamples, wavHeader.Subchunk2Size, totalFrames, wavFile );
                fclose( wavFile );
1

Jaki konkretnie jest problem?

Czy przed odczytem pliku, wskaźnik data.recordedSamples wskazuje na przydzieloną tablicę o wielkości przynajmniej taką, jak wavHeader.Subchunk2Size*totalFrames? Najpierw należy przydzielić pamięć za pomoca malloc (C) lub new (C++), a dopiero potem odczytać dane wpisując je do tej tablicy.

W Twoim kodzie nie widzę momentu przydzielenia pamięci do tablicy pod wskaźnikiem data.recordedSamples.

0

dodałem, ale dalej nie działa ;<

numBytes = numSamples * sizeof(SAMPLE);
if( data.recordedSamples != nullptr )
                free(data.recordedSamples);
                data.recordedSamples = (SAMPLE *) malloc( numBytes );

kompiluje się ale dźwięk jaki odtwarza to jakis szmer(bardziej pyknięcie) i koniec

1

Ale tak nie można. WAV nie ma takiego nagłówka. Poczytaj o formacie RIFF i jak go należy analizować.

0

jak nie ma ;O
jak ja tak zapisałem http://4programmers.net/Forum/C_i_C++/247224-wav_zapis_probek_audio
to co teraz robię to całkowicie nie ma sensu ?

1

jak nie ma ;O

znajdź specyfikację formatu WAV i się do niej stosuj. przykładowo, pomiędzy chunkiem fmt a data może istnieć nieokreślona liczba chunków z metadanymi.
do tego nigdzie nie sprawdzasz pola AudioFormat. a co jeśli WAV jest skompresowany i zawiera strumień np. mp3? oczywiście możesz takiego wave'a odrzucić i obsługiwać tylko nieskompresowane, ale wypadałoby sprawdzać wartość pola i odrzucić taki plik, a nie na siłę z niego czytać.

jak ja tak zapisałem
zależy czy program ma obsługiwać prawdziwe wave'y wygenerowane dowolnym programem zapisującym wave'y, czy tylko pliki wave'opodobne wygenerowane wyłącznie twoim programem z tamtego wątka.

plik WAV jest szczególnym przypadkiem pliku RIFF. to coś jakby binarny XML. nie można takiego pliku traktować jako nagłówek+dane, powinno się analizować dane na poziomie RIFF.

0

o kurczę...
To może najpierw zrobię to ,żeby czytał te wave'opodobne wygenerowane wyłącznie z mojego programu.
A później zajmę się prawidłowym zapisywaniem, odczytywaniem normalnego wave. Dziękuje bardzo za zwrócenie uwgai
W takim razie w tym zapisie do odczytania "mojego wave" (kod powyżej) co jest nie tak ?

2

Tu masz kod czytający poprawnie plik wav:

ifstream is("d:\\plik.wav", ios_base::binary);

char		sign[4];
uint32_t	chunk_size;

is.read(sign, 4).read((char*)&chunk_size, 4);
if(memcmp(sign, "RIFF", 4) != 0) return -1;
is.read(sign, 4);
if(memcmp(sign, "WAVE", 4) != 0) return -1;

while( is.read(sign, 4).read((char*)&chunk_size, 4) )
{
	if(memcmp(sign, "fmt ", 4) == 0)
	{
		vector<char> fmt(chunk_size, 0);
		is.read(&fmt.front(), chunk_size);

		WAVEFORMATEX *pwf = (WAVEFORMATEX*)&fmt.front();
		if(pwf->wFormatTag != WAVE_FORMAT_PCM && pwf->wFormatTag != 3 /* WAVE_FORMAT_IEEE_FLOAT */)
		{
			/* prawdopodobnie kompresja */
			return -1;
		}

		/* tu czytasz parametry z pwf do swoich zmiennych */

		continue;
	}


	if(memcmp(sign, "data", 4) == 0)
	{
		/* tu czytasz 'chunk_size' bajtów próbek */

		break;
	}

	is.seekg(chunk_size, ios::cur); // resztę bloków pomijamy
}

return is ? 0 : -1;

return -1 znaczy że jest błąd i powinieneś przerwać procedurę czytania. Sam sobie dorób odpowiednią obsługę błędów.

0

dziękuje, returny już sobie pozmieniałem, ale
/* tu czytasz parametry z pwf do swoich zmiennych */
hm, mam pobierać tak jak robiłem tam wyżej ? czyli muszę tą strukture dać ?

1

Rób jak Ci wygodnie.

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