E
E
Evgeny Petryaev2020-02-17 17:22:50
C++ / C#
Evgeny Petryaev, 2020-02-17 17:22:50

Faced with the problem of parsing the header wav sound?

I use this code:

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_);

A good file has this title:
5e4aa1b10aa7a864668947.png
A bad one has this:
5e4aa1b806c7a313037418.png
the sound itself is here https://wav-library.net/afrikanskij-konga-baraban-... translated to wav on one of the sites https://audio.online-convert.com /ru/convert-to-wav
Tried adding a char s[178] field; to get to the data field:
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 данные.
};

Got this5e4ad91fe8485223615625.png

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mercury13, 2020-02-17
@Gremlin92

Skip the "left" blocks until we get to data! What else to do?
I got a file with a length of 5.241.822, and there are such blocks: by offset 0C fmt with a length of 0x10, by offset 24=0C+8+10 LIST with a length of AA, and by offset D6=24+8+AA there will be the data we need.
Let me clarify what I meant. RIFF is a standard block format, not limited to WAV. Let's say there is an RMI = RIFF MIDI format. Your solution implies that the "fmt" block is immediately followed by the "data" block, which is not always true.
One more time, man! At offset 0C there will be a fmt block: 4 bytes signature, 4 bytes length and 0x10 bytes data.
Following these 0x10 bytes, at offset 24=0C+8+10, is the LIST block: 4 bytes signature, 4 bytes length, and 0xAA bytes data. The block is not ours - we skip these bytes, and go straight to the offset 0xD6=24+8+AA. There are 4 bytes signature, 4 bytes length and 0x4FFB00 bytes data. We read them.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question