slavavЯ выше привёл сигнал, который хочу прослушать:
Выше я привёл код, он для данного сигнала сойдёт (переполнения не будет, потому что гармоника одна). Я его запускаю и получаю один звук (правильный он или нет сложно сказать, конечно, просто обычный звук длиной 5 сек). Потом я изменяю эту строчку:
Код:
quant = level * 2 / depth;
на
Код:
quant = level * 4 / depth;
то есть по сути увеличиваю количество уровней квантования в два раза. По идее звук должен просто стать в два раза выше, ведь в пике синусоида дойдёт до середины доступного диапазона шестнадцатеричных чисел. Однако в итоге я получаю звук, который отличается не только громкостью, но и какими-то другими параметрами (он становится более глухим и т. д.). То есть это не похоже на то, что мы потянули вниз ползунок громкости.
Вот полный код, он рабочий и создаёт в папке проекте файл out.wav:
Код:
include <iostream>
#include <fstream>
#include <cmath>
float GetSumAm(float* ams, int size)
{
int sum = 0;
for (int i = 0; i < size; ++i)
sum += ams[i];
return sum;
}
void WriteWAVHeader(std::ofstream& file, int sampleRate, int bitsPerSample, int chan, int time)
{
int fileSize = sampleRate * bitsPerSample * chan * time / 8;
int chunkId = 0x46464952,
chunkSize = fileSize + 44 - 8,
format = 0x45564157,
subchunk1Id = 0x20746D66,
subchunk1Size = 0x00000010,
audioFormat = 0x0001,
byteRate = sampleRate * chan * bitsPerSample / 8,
blockAlign = chan * bitsPerSample / 8,
subchunk2Id = 0x61746164,
subchunk2Size = fileSize;
file.write(reinterpret_cast<char*>(&chunkId), 4); //RIFF
file.write(reinterpret_cast<char*>(&chunkSize), 4); //Размер файла минус 8
file.write(reinterpret_cast<char*>(&format), 4); //Формат WAV
file.write(reinterpret_cast<char*>(&subchunk1Id), 4); //Содержит символы fmt
file.write(reinterpret_cast<char*>(&subchunk1Size), 4); //Оставшийся заголовок
file.write(reinterpret_cast<char*>(&audioFormat), 2); //Формат аудио
file.write(reinterpret_cast<char*>(&chan), 2); //Количество каналов
file.write(reinterpret_cast<char*>(&sampleRate), 4); //Частота дискретизации
file.write(reinterpret_cast<char*>(&byteRate), 4); //Количество байт в секунду
file.write(reinterpret_cast<char*>(&blockAlign), 2); //Количество байт для семпла
file.write(reinterpret_cast<char*>(&bitsPerSample), 2); //Количество бит за семпл
file.write(reinterpret_cast<char*>(&subchunk2Id), 4); //Метка start
file.write(reinterpret_cast<char*>(&subchunk2Size), 4); //Размер файла
}
int GetSignal(int sampleRate, int bitsPerSample, int chan, int time,
int f, float* ams, float* harms, int harmsCount, char* filePath)
{
//File
std::ofstream fout;
fout.open(filePath, std::ios::binary | std::ios::out);
//Additional signal parameters and constants
int depth = pow(2, bitsPerSample);
float level = GetSumAm(ams, harmsCount), quant = level * 2 / depth;
const float pi = 3.14159265;
//WAV's header
WriteWAVHeader(fout, sampleRate, bitsPerSample, chan, time);
//Getting signal
for (int t = 0; t < sampleRate * time; ++t)
{
int sample = 0;
for (int j = 0; j < harmsCount; ++j)
sample += static_cast<int>(((ams[j] * sin(2 * pi * f * t * harms[j] / sampleRate) + ams[j]) / quant));
fout.write(reinterpret_cast<char*>(&sample), 2);
}
return 0;
}
int main()
{
int harmsCount = 1;
float* ams = new float[harmsCount];
ams[0] = 10.0;
float* harms = new float[harmsCount];
harms[0] = 1;
char path[9] = "out.wav\0";
GetSignal(44100, 16, 1, 5, 100, ams, harms, harmsCount, path);
}