Gremlin92
@Gremlin92
Целеустремленный

Столкнулся с проблемой парсинга заголовка wav звука?

Юзаю такой код:
struct WAVHEADER
{
	// WAV-формат начинается с RIFF-заголовка:

	// Содержит символы "RIFF" в ASCII кодировке
	// (0x52494646 в big-endian представлении)
	char chunkId[4];

	// 36 + subchunk2Size, или более точно:
	// 4 + (8 + subchunk1Size) + (8 + subchunk2Size)
	// Это оставшийся размер цепочки, начиная с этой позиции.
	// Иначе говоря, это размер файла - 8, то есть,
	// исключены поля chunkId и chunkSize.
	unsigned long chunkSize;

	// Содержит символы "WAVE"
	// (0x57415645 в big-endian представлении)
	char format[4];

	// Формат "WAVE" состоит из двух подцепочек: "fmt " и "data":
	// Подцепочка "fmt " описывает формат звуковых данных:

	// Содержит символы "fmt "
	// (0x666d7420 в big-endian представлении)
	char subchunk1Id[4];

	// 16 для формата PCM.
	// Это оставшийся размер подцепочки, начиная с этой позиции.
	unsigned long subchunk1Size;

	// Аудио формат, полный список можно получить здесь http://audiocoding.ru/wav_formats.txt
	// Для PCM = 1 (то есть, Линейное квантование).
	// Значения, отличающиеся от 1, обозначают некоторый формат сжатия.
	unsigned short audioFormat;

	// Количество каналов. Моно = 1, Стерео = 2 и т.д.
	unsigned short numChannels;

	// Частота дискретизации. 8000 Гц, 44100 Гц и т.д.
	unsigned long sampleRate;

	// sampleRate * numChannels * bitsPerSample/8
	unsigned long byteRate;

	// numChannels * bitsPerSample/8
	// Количество байт для одного сэмпла, включая все каналы.
	unsigned short blockAlign;

	// Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д.
	unsigned short bitsPerSample;

	// Подцепочка "data" содержит аудио-данные и их размер.

	// Содержит символы "data"
	// (0x64617461 в big-endian представлении)
	char subchunk2Id[4];

	// numSamples * numChannels * bitsPerSample/8
	// Количество байт в области данных.
	unsigned long subchunk2Size;

	// Далее следуют непосредственно Wav данные.
};
int j = 0;
#ifdef _WIN32
	file = open("content//konga.wav", _A_ARCH);
#else
	file = open(filename, O_RDONLY);
#endif // _WIN32
	if (file == -1)
	{
		printf("Open failed on input file: %s\n", "content//konga.wav");
#ifdef _WIN32
		wchar_t path[MAX_PATH];
		GetCurrentDirectory(sizeof(path), path);
		std::wcout << path << std::endl;
#endif // _WIN32
	}
	org = 0;

	FILE* file_;
	errno_t err;
	err = fopen_s(&file_, "content//konga.wav", "rb");
	if (err)
	{
		printf_s("Failed open file, error %d", err);
		return 0;
	}

	WAVHEADER header;

	fread_s(&header, sizeof(WAVHEADER), sizeof(WAVHEADER), 1, file_);
	printf("audioformat:%d\n", header.audioFormat);
	printf("bitsPerSample:%d\n", header.bitsPerSample);
	printf("blockAlign:%d\n", header.blockAlign);
	printf("byteRate:%lu\n", header.byteRate);
	printf("chunkId:%s\n", header.chunkId);
	printf("chunkSize:%lu\n", header.chunkSize);
	printf("format:%s\n", header.format);
	printf("numCannels:%d\n", header.numChannels);
	printf("sampleRate:%lu\n", header.sampleRate);
	printf("subchunk1Id:%s\n", header.subchunk1Id);
	printf("subchunk1Size:%lu\n", header.subchunk1Size);
	printf("subchunk2Id:%s\n", header.subchunk2Id);
	printf("subchunk2Size:%lu\n", header.subchunk2Size);
	fclose(file_);

У хорошего файла такой заголовок:
5e4aa1b10aa7a864668947.png
У плохого такой:
5e4aa1b806c7a313037418.png
сам звук тут https://wav-library.net/afrikanskij-konga-baraban-... транслированный в wav на одном из сайтов https://audio.online-convert.com/ru/convert-to-wav
Попробовал добавить поле char s[178]; чтобы дойти до поля data:
struct WAVHEADER
{
	// WAV-формат начинается с RIFF-заголовка:

	// Содержит символы "RIFF" в ASCII кодировке
	// (0x52494646 в big-endian представлении)
	char chunkId[4];

	// 36 + subchunk2Size, или более точно:
	// 4 + (8 + subchunk1Size) + (8 + subchunk2Size)
	// Это оставшийся размер цепочки, начиная с этой позиции.
	// Иначе говоря, это размер файла - 8, то есть,
	// исключены поля chunkId и chunkSize.
	unsigned long chunkSize;

	// Содержит символы "WAVE"
	// (0x57415645 в big-endian представлении)
	char format[4];

	// Формат "WAVE" состоит из двух подцепочек: "fmt " и "data":
	// Подцепочка "fmt " описывает формат звуковых данных:

	// Содержит символы "fmt "
	// (0x666d7420 в big-endian представлении)
	char subchunk1Id[4];

	// 16 для формата PCM.
	// Это оставшийся размер подцепочки, начиная с этой позиции.
	unsigned long subchunk1Size;

	// Аудио формат, полный список можно получить здесь http://audiocoding.ru/wav_formats.txt
	// Для PCM = 1 (то есть, Линейное квантование).
	// Значения, отличающиеся от 1, обозначают некоторый формат сжатия.
	unsigned short audioFormat;

	// Количество каналов. Моно = 1, Стерео = 2 и т.д.
	unsigned short numChannels;

	// Частота дискретизации. 8000 Гц, 44100 Гц и т.д.
	unsigned long sampleRate;

	// sampleRate * numChannels * bitsPerSample/8
	unsigned long byteRate;

	// numChannels * bitsPerSample/8
	// Количество байт для одного сэмпла, включая все каналы.
	unsigned short blockAlign;

	// Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д.
	unsigned short bitsPerSample;
	char s[178l];
	// Подцепочка "data" содержит аудио-данные и их размер.
	// Содержит символы "data"
	// (0x64617461 в big-endian представлении)
	char subchunk2Id[4];

	// numSamples * numChannels * bitsPerSample/8
	// Количество байт в области данных.
	unsigned long subchunk2Size;

	// Далее следуют непосредственно Wav данные.
};

Получил такое 5e4ad91fe8485223615625.png
  • Вопрос задан
  • 343 просмотра
Решения вопроса 2
@Mercury13
Программист на «си с крестами» и не только
Пропускать «левые» блоки, пока не дойдём до data! Что ещё делать?
У меня получился файл длиной 5.241.822, и там такие блоки: по смещению 0C fmt длиной 0x10, по смещению 24=0C+8+10 LIST длиной AA, и по смещению D6=24+8+AA будет нужная нам data.

Уточню, что я имел в виду. RIFF — это стандартный блочный формат, не ограничивающийся WAV’ом. Допустим, есть формат RMI = RIFF MIDI. Ваше решение подразумевает, что за блоком «fmt» сразу идёт блок «data», что не всегда верно.

Ещё раз, мужик! По смещению 0C будет блок «fmt»: 4 байта сигнатура, 4 байта длина и 0x10 байт данные.
За этими 0x10 байтами, по смещению 24=0C+8+10, идёт блок LIST: 4 байта сигнатура, 4 байта длина и 0xAA байт данные. Блок не наш — пропускаем эти байты, и переходим сразу на смещение 0xD6=24+8+AA. Там 4 байта сигнатура, 4 байта длина и 0x4FFB00 байт данные. Их-то и читаем.
Ответ написан
Gremlin92
@Gremlin92 Автор вопроса
Целеустремленный
Решил конвертированием файла из mp3 в wav такой командой
ffmpeg -i konga.mp3 -map_metadata -1 -fflags +bitexact konga.wav
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы