From 9bc043a1592c16995d25051c30165b9e479c52f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maksymilian=20Wilczy=C5=84ski?= Date: Fri, 4 Apr 2025 22:58:40 +0200 Subject: [PATCH] add multiple features 1. dpcm (temporary boilerplate needed, sorry) 2. noise 3. volume 4. multiline comments --- .gitignore | 2 +- snare.wav | Bin 0 -> 8108 bytes synthetizer.cpp | 238 +++++++++++++++++++++++++++++++++++--------- synthetizer.vcxproj | 8 ++ waves.txt | 65 +----------- 5 files changed, 205 insertions(+), 108 deletions(-) create mode 100644 snare.wav diff --git a/.gitignore b/.gitignore index 827658e..49fb7de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .vs/ x64/ -*.wav +output.wav *.vcxproj.user \ No newline at end of file diff --git a/snare.wav b/snare.wav new file mode 100644 index 0000000000000000000000000000000000000000..6e04a05e9557b3f529d4c343b729083bf4475222 GIT binary patch literal 8108 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 RQ-|~MZafiZ;+0@L_&=XEmO=mk literal 0 HcmV?d00001 diff --git a/synthetizer.cpp b/synthetizer.cpp index 1f23864..7dc6134 100644 --- a/synthetizer.cpp +++ b/synthetizer.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -7,13 +8,17 @@ const int SAMPLE_RATE = 44100; const double M_TAU = 6.283185307179586476925286766559; +uint16_t lfsr = 0xACE1u; +unsigned bit; // Enum for waveform types enum Waveform { SINE, TRIANGLE, SAWTOOTH, - SQUARE + SQUARE, + NOISE, + DPCM }; // Structure to hold the waveform parameters @@ -22,9 +27,30 @@ struct Wave { int start_ms; int duration_ms; int frequency; - double volume; // New field for volume control (0.0 to 1.0) + double volume; + double dutyCycle; // For SQUARE + double sweepDepth; // Vibrato or slide + double sweepRate; + double attack; + double decay; + std::string samplePath; + std::vector sampleData; }; +bool loadWavFile(const std::string& path, std::vector& outSamples) { + std::ifstream file(path, std::ios::binary); + if (!file.is_open()) return false; + + file.seekg(44); // skip header + outSamples.clear(); + + int16_t sample; + while (file.read(reinterpret_cast(&sample), sizeof(sample))) { + outSamples.push_back(sample); + } + return true; +} + // Read the parameters from the text file bool loadWaveParams(const std::string& filename, std::vector& waves, int& totalDuration) { std::ifstream file(filename); @@ -34,41 +60,97 @@ bool loadWaveParams(const std::string& filename, std::vector& waves, int& } std::string line; + bool inCommentBlock = false; while (std::getline(file, line)) { + // Remove C-style comments + if (inCommentBlock) { + size_t endComment = line.find("*/"); + if (endComment != std::string::npos) { + inCommentBlock = false; + line = line.substr(endComment + 2); // Remaining part of the line after the comment + } + else { + continue; // Skip entire line if still in a comment block + } + } + + size_t startComment = line.find("/*"); + while (startComment != std::string::npos) { + size_t endComment = line.find("*/", startComment + 2); + if (endComment != std::string::npos) { + line.erase(startComment, endComment - startComment + 2); // Remove the comment + startComment = line.find("/*"); // Look for another comment + } + else { + inCommentBlock = true; + line = line.substr(0, startComment); // Remove everything after /* till end of line + break; + } + } + + // Strip whitespace + line.erase(0, line.find_first_not_of(" \t\r\n")); + if (line.empty() || line[0] == '#') continue; + + // Check if the line defines the total duration if (line.find("TOTAL_DURATION") != std::string::npos) { size_t startPos = line.find("(") + 1; size_t endPos = line.find(")"); totalDuration = std::stoi(line.substr(startPos, endPos - startPos)); + continue; } - else if (line.find("SINE") != std::string::npos || line.find("SAWTOOTH") != std::string::npos || - line.find("SQUARE") != std::string::npos || line.find("TRIANGLE") != std::string::npos) { - std::istringstream ss(line); - std::string waveType; - int start_ms, duration_ms, frequency; - double volume; - ss >> waveType >> start_ms >> duration_ms >> frequency >> volume; - Wave wave; - wave.start_ms = start_ms; - wave.duration_ms = duration_ms; - wave.frequency = frequency; - wave.volume = volume; + // Initialize variables for waveform properties + std::istringstream ss(line); + std::string waveType; + int start_ms, duration_ms, frequency; + double volume = 1.0; + double duty = 0.5; + double sweepDepth = 0.0, sweepRate = 0.0; + double attack = 0.01, decay = 0.2; - if (waveType == "SINE") { - wave.type = SINE; - } - else if (waveType == "SAWTOOTH") { - wave.type = SAWTOOTH; - } - else if (waveType == "SQUARE") { - wave.type = SQUARE; - } - else if (waveType == "TRIANGLE") { - wave.type = TRIANGLE; - } + // Read the basic wave parameters + ss >> waveType >> start_ms >> duration_ms >> frequency >> volume; - waves.push_back(wave); + // Set default values if optional parameters are missing + if (!(ss >> duty)) duty = 0.5; + if (!(ss >> sweepDepth)) sweepDepth = 0.0; + if (!(ss >> sweepRate)) sweepRate = 0.0; + if (!(ss >> attack)) attack = 0.01; + if (!(ss >> decay)) decay = 0.2; + + // Create a new Wave object and set its properties + Wave wave; + wave.start_ms = start_ms; + wave.duration_ms = duration_ms; + wave.frequency = frequency; + wave.volume = volume; + wave.dutyCycle = duty; + wave.sweepDepth = sweepDepth; + wave.sweepRate = sweepRate; + wave.attack = attack; + wave.decay = decay; + + // Determine wave type and set corresponding enum + if (waveType == "SINE") wave.type = SINE; + else if (waveType == "SAWTOOTH") wave.type = SAWTOOTH; + else if (waveType == "SQUARE") wave.type = SQUARE; + else if (waveType == "TRIANGLE") wave.type = TRIANGLE; + else if (waveType == "NOISE") wave.type = NOISE; + else if (waveType == "DPCM") { + wave.type = DPCM; + ss >> wave.samplePath; // Read sample file path for DPCM waves + if (!loadWavFile(wave.samplePath, wave.sampleData)) { + std::cout << "Failed to load sample: " << wave.samplePath << std::endl; + } } + else { + std::cout << "Unknown waveform type: " << waveType << std::endl; + continue; // Skip unknown waveform types + } + + // Add the wave to the vector + waves.push_back(wave); } return true; @@ -96,43 +178,105 @@ double sawtoothWave(double frequency, double time) { return 2 * phase - 1; // Ramp from -1 to 1 } -double squareWave(double frequency, double time) { +double squareWave(double frequency, double time, double duty = 0.5) { double period = 1.0 / frequency; - double phase = fmod(time, period) / period; // Normalized phase (0 to 1) - return phase < 0.5 ? 1.0 : -1.0; // 1 for the first half, -1 for the second half + double phase = fmod(time, period) / period; // 0 to 1 + return phase < duty ? 1.0 : -1.0; } // Mix the waveforms with volume control -double generateWave(Waveform waveform, double frequency, double time) { +double generateWave(Waveform waveform, double frequency, double time, double duty = 0.5) { switch (waveform) { - case SINE: - return sineWave(frequency, time); - case TRIANGLE: - return triangleWave(frequency, time); - case SAWTOOTH: - return sawtoothWave(frequency, time); - case SQUARE: - return squareWave(frequency, time); - default: - return sineWave(frequency, time); // Default to sine wave + case SINE: return sineWave(frequency, time); + case TRIANGLE: return triangleWave(frequency, time); + case SAWTOOTH: return sawtoothWave(frequency, time); + case SQUARE: return squareWave(frequency, time, duty); + default: return sineWave(frequency, time); } } +double applyVibrato(double baseFreq, double time, double depth = 5.0, double rate = 5.0) { + return baseFreq + depth * std::sin(M_TAU * rate * time); +} + +double applyEnvelope(double time, double startTime, double duration, double volume, double attack, double decay) { + double elapsed = time - startTime; + if (elapsed < 0.0) return 0.0; + + if (elapsed < attack) { + // Attack phase: ramp up from 0 to volume + return volume * (elapsed / attack); + } + + if (elapsed < (attack + decay)) { + // Decay phase: ramp down to 0 + return volume * (1.0 - ((elapsed - attack) / decay)); + } + + // After envelope ends + return 0.0; +} + +double noiseWave() { + // 16-bit Galois LFSR + bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1; + lfsr = (lfsr >> 1) | (bit << 15); + return ((lfsr & 1) ? 1.0 : -1.0); // White-ish noise +} + std::vector generateAudio(const std::vector& waves, int totalDuration) { std::vector samples(SAMPLE_RATE * totalDuration / 1000, 0); // Initialize with zeros - // Process each wave for (const auto& wave : waves) { int startSample = wave.start_ms * SAMPLE_RATE / 1000; int endSample = (wave.start_ms + wave.duration_ms) * SAMPLE_RATE / 1000; - // Generate the waveform for the specified duration + if (wave.type == DPCM) { + // DPCM Sample Playback (raw PCM sample, assumed 16-bit mono) + for (int i = 0; i < wave.sampleData.size(); ++i) { + int t = startSample + i; + if (t >= samples.size()) break; + + double envelopeVol = applyEnvelope( + t / (double)SAMPLE_RATE, + wave.start_ms / 1000.0, + wave.duration_ms / 1000.0, + 1.0, wave.attack, wave.decay + ); + + samples[t] += static_cast(wave.sampleData[i] * envelopeVol); + } + continue; // Skip standard waveform generation for DPCM + } + for (int t = startSample; t < endSample; ++t) { - if (t >= samples.size()) break; // Prevent out-of-bounds access + if (t >= samples.size()) break; + double time = static_cast(t) / SAMPLE_RATE; - double sample = generateWave(wave.type, wave.frequency, time); - sample *= wave.volume; // Apply volume - samples[t] += static_cast(sample * 32767); // Linear mixing + double startTime = wave.start_ms / 1000.0; + double relTime = time - startTime; + if (relTime < 0) continue; + + // Frequency sweep / vibrato + double modFreq = wave.frequency + wave.sweepDepth * std::sin(M_TAU * wave.sweepRate * time); + + // Generate waveform + double rawSample = 0.0; + if (wave.type == NOISE) { + rawSample = noiseWave(); // LFSR noise + } + else { + rawSample = generateWave(wave.type, modFreq, time, wave.dutyCycle); + } + + // Envelope application + double envelopeVolume = applyEnvelope(time, startTime, wave.duration_ms / 1000.0, wave.volume, wave.attack, wave.decay); + + // Final sample + double finalSample = rawSample * envelopeVolume; + + // Mix into audio buffer + samples[t] += static_cast(std::clamp(finalSample * 32767.0, -32768.0, 32767.0)); } } diff --git a/synthetizer.vcxproj b/synthetizer.vcxproj index 6c7d13f..b80f998 100644 --- a/synthetizer.vcxproj +++ b/synthetizer.vcxproj @@ -76,6 +76,8 @@ true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 + stdc17 Console @@ -90,6 +92,8 @@ true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 + stdc17 Console @@ -104,6 +108,8 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 + stdc17 Console @@ -118,6 +124,8 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 + stdc17 Console diff --git a/waves.txt b/waves.txt index a8ce288..1b7288b 100644 --- a/waves.txt +++ b/waves.txt @@ -1,61 +1,6 @@ -TOTAL_DURATION(10000) +TOTAL_DURATION(3000) // 3 seconds total -SQUARE 0 400 392 0.7 -SAWTOOTH 0 400 392 0.4 -SINE 0 400 392 0.3 -TRIANGLE 0 400 392 0.2 - -SQUARE 450 400 392 0.7 -SAWTOOTH 450 400 392 0.4 -SINE 450 400 392 0.3 -TRIANGLE 450 400 392 0.2 - -SQUARE 900 800 440 0.7 -SAWTOOTH 900 800 440 0.4 -SINE 900 800 440 0.3 -TRIANGLE 900 800 440 0.2 - -SQUARE 1800 800 392 0.7 -SAWTOOTH 1800 800 392 0.4 -SINE 1800 800 392 0.3 -TRIANGLE 1800 800 392 0.2 - -SQUARE 2700 800 523 0.7 -SAWTOOTH 2700 800 523 0.4 -SINE 2700 800 523 0.3 -TRIANGLE 2700 800 523 0.2 - -SQUARE 3600 1600 494 0.7 -SAWTOOTH 3600 1600 494 0.4 -SINE 3600 1600 494 0.3 -TRIANGLE 3600 1600 494 0.2 - -SQUARE 5400 400 392 0.7 -SAWTOOTH 5400 400 392 0.4 -SINE 5400 400 392 0.3 -TRIANGLE 5400 400 392 0.2 - -SQUARE 5850 400 392 0.7 -SAWTOOTH 5850 400 392 0.4 -SINE 5850 400 392 0.3 -TRIANGLE 5850 400 392 0.2 - -SQUARE 6300 800 440 0.7 -SAWTOOTH 6300 800 440 0.4 -SINE 6300 800 440 0.3 -TRIANGLE 6300 800 440 0.2 - -SQUARE 7200 800 392 0.7 -SAWTOOTH 7200 800 392 0.4 -SINE 7200 800 392 0.3 -TRIANGLE 7200 800 392 0.2 - -SQUARE 8100 800 587 0.7 -SAWTOOTH 8100 800 587 0.4 -SINE 8100 800 587 0.3 -TRIANGLE 8100 800 587 0.2 - -SQUARE 9000 1600 523 0.7 -SAWTOOTH 9000 1600 523 0.4 -SINE 9000 1600 523 0.3 -TRIANGLE 9000 1600 523 0.2 +SINE 0 1000 440 1.0 0 3 5 0.05 0.3 // sine with slow vibrato and long decay +SQUARE 500 1000 330 0.7 0.25 6 4 0.01 0.2 // square with duty cycle and sweep +NOISE 1500 400 0 0.8 0 0 0 0.02 0.1 // noise burst +DPCM 2000 800 /* boilerplate */ 0 0 0 0 0 0 1.0 snare.wav \ No newline at end of file