Anonymous
Раздел выпуска конверта ADSR не работает
Сообщение
Anonymous » 31 окт 2025, 19:28
Я пытаюсь создать синтезатор цифрового звука с нуля на C++, используя комбинацию ресурсов. Я использую функции из raylib для воспроизведения необработанного аудиопотока. Вот код:
Код: Выделить всё
#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;
}
Все части конверта работают нормально, кроме Release. Звук просто обрывается. Я возился с кодом, внося различные изменения, пытаясь заставить его работать, но он продолжает отключаться. LLM тоже не смогли это исправить (Клод Код). Наконец я решил, что это может быть проблема с типом данных, и внимательно просмотрел код, но на самом деле не нашел таких ошибок. Теперь в отчаянии я обращаюсь к StackOverflow. Пожалуйста, помогите.
Подробнее здесь:
https://stackoverflow.com/questions/797 ... ot-working
1761928104
Anonymous
Я пытаюсь создать синтезатор цифрового звука с нуля на C++, используя комбинацию ресурсов. Я использую функции из raylib для воспроизведения необработанного аудиопотока. Вот код: [code]#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; } [/code] Все части конверта работают нормально, кроме Release. Звук просто обрывается. Я возился с кодом, внося различные изменения, пытаясь заставить его работать, но он продолжает отключаться. LLM тоже не смогли это исправить (Клод Код). Наконец я решил, что это может быть проблема с типом данных, и внимательно просмотрел код, но на самом деле не нашел таких ошибок. Теперь в отчаянии я обращаюсь к StackOverflow. Пожалуйста, помогите. Подробнее здесь: [url]https://stackoverflow.com/questions/79792129/release-section-of-adsr-envelope-not-working[/url]