Код: Выделить всё
#include
#include
#include
#include "raylib/raylib.h"
using namespace std;
#define SIGNAL_SIZE 1024
#define SAMPLE_RATE 44100
#define BITS_PER_SAMPLE 16
#define NUM_KEYS 15
#define AMPLITUDE 8000
const float BASE_FREQUENCY = 220.0f;
const float twelfthRootOf2 = pow(2.0f, 1.0f / 12.0f);
float signal[SIGNAL_SIZE];
const float deltaTime = 1 / (float)SAMPLE_RATE;
double elapsedTime = 0.0;
struct ADSREnvelope {
double attackTime;
double decayTime;
double releaseTime;
double startAmplitude;
double sustainAmplitude;
double keydownTime;
double keyupTime;
bool notePressed;
ADSREnvelope() {
attackTime = 1.0;
decayTime = 0.01;
releaseTime = 1.0;
startAmplitude = 1.0;
sustainAmplitude = 0.8;
keydownTime = 0.0;
keyupTime = 0.0;
notePressed = false;
}
void keydown(double _keydownTime) {
keydownTime = _keydownTime;
notePressed = true;
}
void keyup(double _keyupTime) {
keyupTime = _keyupTime;
notePressed = false;
}
double getAmplitude(double currTime) {
double currAmp = 0.0;
double lifetime = currTime - keydownTime;
if (notePressed) {
if (lifetime attackTime && lifetime (attackTime + decayTime)) {
currAmp = sustainAmplitude;
}
}
else {
currAmp = (((currTime - keyupTime) / releaseTime) * (0 - sustainAmplitude)) + sustainAmplitude;
}
if (currAmp < 0.00001) {
currAmp = 0;
}
return currAmp;
}
};
ADSREnvelope envelope;
vector keysPressed(NUM_KEYS, false);
vector phases(NUM_KEYS, 0.0f);
float squareWave(float phase) {
float output = sinf(2 * PI * phase);
if (output < 0) {
return -1;
}
else {
return 1;
}
}
float triangleWave(float phase) {
return asinf(sinf(2 * PI * phase));
}
float sawWave(float phase) {
return (2 * phase) - 1;
}
void updateStream(void* buffer, unsigned int frames) {
short* d = (short*)buffer;
float prevSample = 0.0f;
for (unsigned int n = 0; n < frames; n++) {
float sample = 0.0f;
int activeKeys = 0;
for (int i = 0; i < NUM_KEYS; i++) {
if (keysPressed[i]) {
float currFrequency = BASE_FREQUENCY * pow(twelfthRootOf2, i);
float increment = currFrequency / SAMPLE_RATE;
sample += sawWave(phases[i]);
phases[i] += increment;
if (phases[i] > 1.0f) {
phases[i] -= 1.0f;
}
activeKeys++;
}
}
if (activeKeys > 0) {
sample /= activeKeys;
sample *= 1.3;
prevSample = sample;
}
else {
sample = prevSample;
}
d[n] = envelope.getAmplitude(elapsedTime) * AMPLITUDE * sample;
elapsedTime += deltaTime;
}
}
int main(void)
{
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "noyz");
SetTargetFPS(60);
// AUDIO
InitAudioDevice();
SetAudioStreamBufferSizeDefault(SIGNAL_SIZE);
AudioStream stream = LoadAudioStream(SAMPLE_RATE, BITS_PER_SAMPLE, 1);
SetAudioStreamCallback(stream, updateStream);
PlayAudioStream(stream);
vector notes = { "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
KeyboardKey keys[] = { KEY_Z, KEY_S, KEY_X, KEY_C, KEY_F, KEY_V, KEY_G, KEY_B, KEY_N, KEY_J, KEY_M, KEY_K, KEY_COMMA, KEY_L, KEY_PERIOD };
int startEnvelope = false;
while (!WindowShouldClose())
{
bool play = false;
string chord = "";
for (int i = 0; i < 15; i++) {
if (IsKeyDown(keys[i])) {
//outputFrequency = BASE_FREQUENCY * pow(twelfthRootOf2, i);
play = true;
keysPressed[i] = true;
chord += notes[i] + " - ";
}
else {
keysPressed[i] = false;
}
}
if (play) {
if (!envelope.notePressed) {
envelope.keydown(elapsedTime);
}
}
else {
if (envelope.notePressed) {
envelope.keyup(elapsedTime);
}
}
BeginDrawing();
ClearBackground(BLACK);
Vector2 txtDim = MeasureTextEx(GetFontDefault(), chord.c_str(), 32, 0);
DrawText(chord.c_str(), 400 - (txtDim.x / 2), 225 - (txtDim.y / 2), 32, RAYWHITE);
EndDrawing();
}
CloseWindow();
return 0;
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... ot-working