Это рабочая и проверенная версия для C ++.
createTone()
создает заголовок и генерирует тональные данные. Эта статья в Википедии описывает значения переменных заголовка DATA_OFFSET
, DATA_SIZE
, ENCODING
, SAMPLE_RATE
и CHANNELS
.
ПРИМЕЧАНИЕ: имейте в виду, что файлы .au генерируются с использованием BIG ENDIAN, поэтому при компиляции на Intel x86 / x64 вам нужно будет выполнить преобразование, поэтому загружается htonl
.
В этом коде используется линейная модуляция PCM 8 длядругие модуляции вам нужно будет изменить / заменить pcm8()
функция.
#include <iostream>
#include <fstream>
#include <sstream>
#include <math.h>
#include <arpa/inet.h>
const int MAGIC_WORD = htonl(0x2e736e64);
const int DATA_OFFSET = htonl(24);
const int DATA_SIZE = htonl(0xffffffff);
const int ENCODING = htonl(0x00000002);
const int SAMPLE_RATE = 0x00001F40;
const int CHANNELS = htonl(0x00000005);
const double PI = 3.14159265358979323846L;
const int PCM_MAX = 0xffffffff;
int pcm8(double value) {
double v = ((value + 1) / 2);
double delta = 1.0 / pow(2, 8);
double ret = round(v / delta);
int r = (int) ret;
return r;
}
void createTone(int duration, double frec) {
std::ofstream file;
file.open("tone.au", std::ios::binary);
// header
const int sampleRate = htonl(SAMPLE_RATE);
file.write((char*) &MAGIC_WORD, sizeof(int));
file.write((char*) &DATA_OFFSET, sizeof(int));
file.write((char*) &DATA_SIZE, sizeof(int));
file.write((char*) &ENCODING, sizeof(int));
file.write((char*) &sampleRate, sizeof(int));
file.write((char*) &CHANNELS, sizeof(int));
// data
double t = 0;
while (t < duration) {
int level = htonl(pcm8(sin(2 * PI * frec * t)));
file.write((char*) &level, sizeof(int));
t += 1.0 / ((double) SAMPLE_RATE);
}
file.close();
}
int main(int argc, char** argv) {
createTone(4, 440.0);
return 0;
}