Лисья Нора

Оглавление


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

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

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

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 -- размер оставшихся данных

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

struct WAVEFMTHEADER head = {
0x46464952,
(wav_size + 0x24),
0x45564157,
0x20746d66,
16, // 16=PCM
1, // Тип
2, // Каналы
44100, // Частота дискретизации
88200, // Байт в секунду
2, // Байт на семпл (1+1)
8, // Битность
0x61746164, // "data"
wav_size
};
 
fseek(wave_file, 0, SEEK_SET);
fwrite(&head, 1, sizeof(WAVEFMTHEADER), wave_file);

§ Класс для WAV

#include <stdlib.h>
#include <stdio.h>
 
// 44 байта https://audiocoding.ru/articles/2008-05-22-wav-file-structure/
struct __attribute__((__packed__)) WAVEFMTHEADER {
 
unsigned int chunkId; // RIFF 0x52494646
unsigned int chunkSize;
unsigned int format; // WAVE 0x57415645
unsigned int subchunk1Id; // fmt (0x666d7420)
unsigned int subchunk1Size; // 16
unsigned short audioFormat; // 1
unsigned short numChannels; // 2
unsigned int sampleRate; // 44100
unsigned int byteRate; // 88200
unsigned short blockAlign; // 2
unsigned short bitsPerSample; // 8
unsigned int subchunk2Id; // data 0x64617461
unsigned int subchunk2Size; // Количество байт в области данных.
};

§ Twave

class Twave {
 
protected:
 
unsigned int frequency = 44100;
unsigned short channels = 2;
unsigned int wav_size = 0;
unsigned int top = 0;
unsigned char* data = NULL;
 
public:
 
// Инициализация настроек звука
Twave(int _frequency = 44100, int _channels = 2) {
 
frequency = _frequency;
channels = _channels;
top = 0;
wav_size = 0;
data = NULL;
}
 
// Выгрузка из памяти
~Twave() {
if (data) free(data);
}
 
int freq() { return frequency; }
 
// Добавить новый сэмпл
void add(unsigned char lf, unsigned char rt = 0) {
 
// Есть необходимость в динамическом увеличении памяти
if (wav_size == 0) {
 
top = frequency * channels;
data = (unsigned char*) malloc(top);
 
} else if (wav_size >= top) {
 
top *= 2;
data = (unsigned char*) realloc(data, top);
}
 
if (channels >= 1) data[wav_size++] = lf;
if (channels == 2) data[wav_size++] = rt;
}
 
// Сохранить файл с данными
void save(const char* filename) {
 
unsigned int _wavesize = wav_size + 0x24;
unsigned int _byteinsec = frequency * channels;
 
struct WAVEFMTHEADER head = {
0x46464952, // RIFF
_wavesize,
0x45564157, // WAVE
0x20746d66, // Fmt
16, // 16=PCM
1, // Тип
channels, // Каналы
frequency, // Частота дискретизации
_byteinsec, // Байт в секунду
channels, // Байт на семпл (1+1)
8, // Битность
0x61746164, // "data"
wav_size
};
 
FILE* fp = fopen(filename, "wb");
if (fp) {
 
fseek(fp, 0, SEEK_SET);
fwrite(&head, 1, sizeof(WAVEFMTHEADER), fp);
fwrite(data, 1, wav_size, fp);
fclose(fp);
}
}
};