§ Структура заголовка

Замечание. Дана частичная информация по формату WAV. Только для скоростного пользования.
unsigned int   -- 4 байта (32 бита)
unsigned short -- 2 байта (16 бит)
1// 44 байта https://audiocoding.ru/articles/2008-05-22-wav-file-structure/
2struct __attribute__((__packed__)) WAVEFMTHEADER {
3
4    unsigned int    chunkId;        // RIFF 0x52494646
5    unsigned int    chunkSize;
6    unsigned int    format;         // WAVE 0x57415645
7    unsigned int    subchunk1Id;    // fmt (0x666d7420)
8    unsigned int    subchunk1Size;  // 16
9    unsigned short  audioFormat;    // 1
10    unsigned short  numChannels;    // 2
11    unsigned int    sampleRate;     // 44100
12    unsigned int    byteRate;       // 88200
13    unsigned short  blockAlign;     // 2
14    unsigned short  bitsPerSample;  // 8
15    unsigned int    subchunk2Id;    // data 0x64617461
16    unsigned int    subchunk2Size;  // Количество байт в области данных.
17};

§ Описание полей

chunkId       -- сигнатура "RIFF"
chunkSize     -- размер заголовка 0x24 + размер данных (либо размер файла)
format        -- сигнатура "WAVE"
subchunk1Id   -- сигнатура "fmt "
subchunk1Size -- 16 (PCM 8 Левый + 8 Правый)
audioFormat   -- тип 1 (обычный)
numChannels   -- 2, количество каналов (стерео)
sampleRate    -- 44100, xастота дискретизации
bitsPerSample -- 88200, байт на 1 семпл (2 канала x 44100)
blockAlign    -- 2 блока на семпл (2 байта)
bitsPerSample -- 8 бит
subchunk2Id   -- сигнатура "data"
subchunk2Size -- размер оставшихся данных

§ Запись заголовка на С

  • wav_size — полный размер данных
  • FILE* wave_file — файл
1struct WAVEFMTHEADER head = {
2    0x46464952,
3    (wav_size + 0x24),
4    0x45564157,
5    0x20746d66,
6    16,     // 16=PCM
7    1,      // Тип
8    2,      // Каналы
9    44100,  // Частота дискретизации
10    88200,  // Байт в секунду
11    2,      // Байт на семпл (1+1)
12    8,      // Битность
13    0x61746164, // "data"
14    wav_size
15};
16
17fseek(wave_file, 0, SEEK_SET);
18fwrite(&head, 1, sizeof(WAVEFMTHEADER), wave_file);

§ Класс для WAV

1#include <stdlib.h>
2#include <stdio.h>
3
4// 44 байта https://audiocoding.ru/articles/2008-05-22-wav-file-structure/
5struct __attribute__((__packed__)) WAVEFMTHEADER {
6
7    unsigned int    chunkId;        // RIFF 0x52494646
8    unsigned int    chunkSize;
9    unsigned int    format;         // WAVE 0x57415645
10    unsigned int    subchunk1Id;    // fmt (0x666d7420)
11    unsigned int    subchunk1Size;  // 16
12    unsigned short  audioFormat;    // 1
13    unsigned short  numChannels;    // 2
14    unsigned int    sampleRate;     // 44100
15    unsigned int    byteRate;       // 88200
16    unsigned short  blockAlign;     // 2
17    unsigned short  bitsPerSample;  // 8
18    unsigned int    subchunk2Id;    // data 0x64617461
19    unsigned int    subchunk2Size;  // Количество байт в области данных.
20};
21
22class Twave {
23
24protected:
25
26    unsigned int    frequency   = 44100;
27    unsigned short  channels    = 2;
28    unsigned int    wav_size    = 0;
29    unsigned int    top         = 0;
30    unsigned char*  data        = NULL;
31
32public:
33
34    // Инициализация настроек звука
35    Twave(int _frequency = 44100, int _channels = 2) {
36
37        frequency   = _frequency;
38        channels    = _channels;
39        top         = 0;
40        wav_size    = 0;
41        data        = NULL;
42    }
43
44    // Выгрузка из памяти
45    ~Twave() {
46        if (data) free(data);
47    }
48
49    int freq() { return frequency; }
50
51    // Добавить новый сэмпл
52    void add(unsigned char lf, unsigned char rt = 0) {
53
54        // Есть необходимость в динамическом увеличении памяти
55        if (wav_size == 0) {
56
57            top  = frequency * channels;
58            data = (unsigned char*) malloc(top);
59
60        } else if (wav_size >= top) {
61
62            top *= 2;
63            data = (unsigned char*) realloc(data, top);
64        }
65
66        if (channels >= 1) data[wav_size++] = lf;
67        if (channels == 2) data[wav_size++] = rt;
68    }
69
70    // Сохранить файл с данными
71    void save(const char* filename) {
72
73        unsigned int _wavesize  = wav_size + 0x24;
74        unsigned int _byteinsec = frequency * channels;
75
76        struct WAVEFMTHEADER head = {
77            0x46464952, // RIFF
78            _wavesize,
79            0x45564157, // WAVE
80            0x20746d66, // Fmt
81            16,         // 16=PCM
82            1,          // Тип
83            channels,   // Каналы
84            frequency,  // Частота дискретизации
85            _byteinsec, // Байт в секунду
86            channels,   // Байт на семпл (1+1)
87            8,          // Битность
88            0x61746164, // "data"
89            wav_size
90        };
91
92        FILE* fp = fopen(filename, "wb");
93        if (fp) {
94
95            fseek(fp, 0, SEEK_SET);
96            fwrite(&head, 1, sizeof(WAVEFMTHEADER), fp);
97            fwrite(data, 1, wav_size, fp);
98            fclose(fp);
99        }
100    }
101};