#include #include #include #include #include #include const int SAMPLE_RATE = 44100; const double TWO_PI = 6.283185307179586476925286766559; // Enum for waveform types enum Waveform { SINE, TRIANGLE, SAWTOOTH, SQUARE }; // Structure to hold the waveform parameters struct Wave { Waveform type; int start_ms; int duration_ms; int frequency; double volume; // New field for volume control (0.0 to 1.0) }; // Read the parameters from the text file bool loadWaveParams(const std::string& filename, std::vector& waves, int& totalDuration) { std::ifstream file(filename); if (!file.is_open()) { std::cerr << "Error opening file!" << std::endl; return false; } std::string line; while (std::getline(file, line)) { 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)); } 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; 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; } waves.push_back(wave); } } return true; } // Waveform generation functions double sineWave(double frequency, double time) { return std::sin(TWO_PI * frequency * time); } double triangleWave(double frequency, double time) { double period = 1.0 / frequency; double phase = fmod(time, period) / period; // Normalized phase (0 to 1) if (phase < 0.5) { return 4 * phase - 1; // Rising part of the triangle } else { return 3 - 4 * phase; // Falling part of the triangle } } double sawtoothWave(double frequency, double time) { double period = 1.0 / frequency; double phase = fmod(time, period) / period; // Normalized phase (0 to 1) return 2 * phase - 1; // Ramp from -1 to 1 } double squareWave(double frequency, double time) { 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 } // Mix the waveforms with volume control double generateWave(Waveform waveform, double frequency, double time) { 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 } } 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 for (int t = startSample; t < endSample; ++t) { if (t >= samples.size()) break; // Prevent out-of-bounds access 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 } } return samples; } // Write WAV file void writeWav(const std::string& filename, const std::vector& samples) { std::ofstream file(filename, std::ios::binary); // WAV Header struct WAVHeader { char riff[4]; // "RIFF" uint32_t fileSize; char wave[4]; // "WAVE" char fmt[4]; // "fmt " uint32_t fmtSize; uint16_t audioFormat; uint16_t numChannels; uint32_t sampleRate; uint32_t byteRate; uint16_t blockAlign; uint16_t bitsPerSample; char data[4]; // "data" uint32_t dataSize; }; WAVHeader header; memcpy(header.riff, "RIFF", 4); header.fileSize = 36 + samples.size() * sizeof(int16_t); memcpy(header.wave, "WAVE", 4); memcpy(header.fmt, "fmt ", 4); header.fmtSize = 16; header.audioFormat = 1; // PCM header.numChannels = 1; // Mono header.sampleRate = SAMPLE_RATE; header.byteRate = SAMPLE_RATE * sizeof(int16_t); header.blockAlign = sizeof(int16_t); header.bitsPerSample = 16; memcpy(header.data, "data", 4); header.dataSize = samples.size() * sizeof(int16_t); file.write(reinterpret_cast(&header), sizeof(header)); file.write(reinterpret_cast(samples.data()), samples.size() * sizeof(int16_t)); } int main() { std::vector waves; int totalDuration = 0; // Load the wave parameters from a text file if (!loadWaveParams("waves.txt", waves, totalDuration)) { std::cerr << "Failed to load wave parameters!" << std::endl; return 1; } // Generate the audio by mixing the waveforms std::vector samples = generateAudio(waves, totalDuration); // Write the audio to a WAV file writeWav("output.wav", samples); std::cout << "WAV file generated: output.wav" << std::endl; return 0; }