Zapis .wav

0

Witam mam problem przy zapisie sampli do pliku .wav.

Header wczytuje poprawnie.

#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef uint32_t DWORD;
typedef uint16_t WORD;
typedef uint8_t BYTE;

#pragma pack(push, 1)
typedef struct
{
    BYTE chunk_id[4];
    DWORD chunk_size;
    BYTE format[4];
    BYTE subchunk1_id[4];
    DWORD subchunk1_size;
    WORD audio_format;
    WORD num_channels;
    DWORD sample_rate;
    DWORD byte_rate;
    WORD block_align;
    WORD bits_per_sample;
    BYTE sub_chunk2_id[4];
    DWORD sub_chunk2_size;
}header;
#pragma pack(pop)

Problem raczej jest przy zamianie tablicy char na inta, bo np jeżeli pobiore sampel i od razu go zapisze to drugi plik jest tworzony poprawnie.
W taki sposób:

fread(sampel, size_of_sample, 1, fpt);
fwrite(sampel, size_of_sample, 1, fpt2);

Póki co ten program powinien pobierać jeden plik wave i tworzyć taki sam drugi, ale bede musiał zmieniać potem sample, dlatego zmieniam je na inta.
Dodatkowo teń dźwięk nie jest całkowicie zły. Występuje szum, ale te pliki są podobne.

sammples = hpt->num_channels*hpt->sub_chunk2_size /hpt->block_align;   // Ilosc sampli, każdy kanał jest liczony oddzielnie czyli jako pojedynczy sampel

int size_of_sample = hpt->block_align / hpt->num_channels;  // Rozmiar pojedynczego sampla.

char* sampel = malloc(sizeof(char) * size_of_sample);   tablica do zapisania sampla 

int data; // wartosc sampla z tego co wiem ma byc to integer moze tu jest blad?

for (int i = 0; i < sammples; ++i)
	{
		fread(sampel, size_of_sample, 1, fpt);
		if (size_of_sample == 4)
		{
			data = sampel[0] | (sampel[1] << 8) | (sampel[2] << 16) | (sampel[3] << 24);
		}
		if (size_of_sample == 2)
		{
			data = sampel[0] | (sampel[1] << 8);
		}
		else
		{
			data = sampel[0];
		}

/* Ponizej zaczyna sie zamiana na inta*/
		if (size_of_sample == 4)
		{
			data = sampel[0] | (sampel[1] >> 8) | (sampel[2] >> 16) | (sampel[3] >> 24);
		}
		if (size_of_sample == 2)
		{
			sampel[0] = data;
			sampel[1] = data>>8;
		}
		else
		{
			sampel[0] = data;
		}
		fwrite(sampel, size_of_sample, 1, fpt2);
		




	}
0

Żeby nie bawić się za bardzo takimi szczegółami to możesz użyć tej biblioteki: https://www.un4seen.com/. Ogólnie to pierwszy "if" po tym komentarzu :"/* Ponizej zaczyna sie zamiana na inta*/" wydaje mi się podejrzany, skoro chcesz zapisać dane, to czemu znowu ładujesz je do data?

0

Niestety nie mogę używać bibliotek. Poprawię drugi komentarz bo powinno być: " / Ponizej zaczyna sie zamiana na tablice char/;"

1

data = sampel[0] | (sampel[1] << 8) | (sampel[2] << 16) | (sampel[3] << 24);

Dlaczego tak, a nie po prostu:

data = *((int*)sampel);

Analogicznie robisz dla 16-bitowych próbek.

data = sampel[0];

Próbki 8-bitowe nie są kodowanie w U2. Zero, jeśli dobrze pamiętam, to wartość 128.

0

Dziękuję, teraz działa poprawnie. Z tego co rozumiem nie potrzebnie zmieniałem kolejność bajtów, kiedy wszystkie dane są little endian i wczytywały się poprawnie, a tu zacząłem zmieniać na big endian i prawdopodobnie stąd ten szum.

1
data = *((int*)sampel);

To jest UB. Jak chcesz żeby wszystko było lege artis, użyj memcpy()

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.