§ Топ-уровень

Это простой класс для создания wav-файла с разной частотой (11025, 22050, 44100) и каналами (1-моно или 2-стерео). Здесь используется 8-битный диапазон звука (от 0 до 255).
1#include <stdio.h>
2#include <stdlib.h>
3#include "wave.cc"
4
5int main(int argc, char* argv[]) {
6
7    Twave wave(44100, 1); // Моно, 44100 Гц
8    for (int i = 0; i < 44100; i++) wave.add(i & 255); // Пилообразная волна
9    wave.save("hello.wav");
10    return 0;
11}

§ Код класса

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};
18
19class Twave {
20
21protected:
22
23    unsigned int    frequency   = 44100;
24    unsigned short  channels    = 2;
25    unsigned int    wav_size    = 0;
26    unsigned int    top         = 0;
27    unsigned char*  data        = NULL;
28
29public:
30
31    // Инициализация настроек звука
32    Twave(int _frequency = 44100, int _channels = 2) {
33
34        frequency   = _frequency;
35        channels    = _channels;
36        top         = 0;
37        wav_size    = 0;
38        data        = NULL;
39    }
40
41    // Выгрузка из памяти
42    ~Twave() {
43        if (data) free(data);
44    }
45
46    // Добавить новый сэмпл
47    void add(unsigned char lf, unsigned char rt = 0) {
48
49        // Есть необходимость в динамическом увеличении памяти
50        if (wav_size == 0) {
51
52            top  = frequency * channels;
53            data = (unsigned char*) malloc(top);
54
55        } else if (wav_size >= top) {
56
57            top *= 2;
58            data = (unsigned char*) realloc(data, top);
59        }
60
61        if (channels >= 1) data[wav_size++] = lf;
62        if (channels == 2) data[wav_size++] = rt;
63    }
64
65    // Сохранить файл с данными
66    void save(const char* filename) {
67
68        unsigned int _wavesize  = wav_size + 0x24;
69        unsigned int _byteinsec = frequency * channels;
70
71        struct WAVEFMTHEADER head = {
72            0x46464952, // RIFF
73            _wavesize,
74            0x45564157, // WAVE
75            0x20746d66, // Fmt
76            16,         // 16=PCM
77            1,          // Тип
78            channels,   // Каналы
79            frequency,  // Частота дискретизации
80            _byteinsec, // Байт в секунду
81            channels,   // Байт на семпл (1+1)
82            8,          // Битность
83            0x61746164, // "data"
84            wav_size
85        };
86
87        FILE* fp = fopen(filename, "wb");
88        if (fp) {
89
90            fseek(fp, 0, SEEK_SET);
91            fwrite(&head, 1, sizeof(WAVEFMTHEADER), fp);
92            fwrite(data, 1, wav_size, fp);
93            fclose(fp);
94        }
95    }
96};