commit 5e17568bbb23024be0ec831d0ff4d2618581faa6 Author: Teo-CD Date: Sat Apr 17 19:09:06 2021 +0100 Basic functionnality and configuration posssible diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34d7acc --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**/.idea +**/cmake-build*/ +scream.mp3 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0a44781 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.17) +project(ScreamingHot) + +set(CMAKE_CXX_STANDARD 17) + +find_package(SFML COMPONENTS window audio REQUIRED) +if(NOT SFML_FOUND) + message(FATAL_ERROR "SFML could not be found") +endif() + +add_executable(ScreamingHot main.cpp) + +target_link_libraries(ScreamingHot + sfml-window + sfml-audio) diff --git a/README.md b/README.md new file mode 100644 index 0000000..cfa781c --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# Screaming Hot + +Make your computer scream when it gets hot ! + +# Limitations + +This only handles temperature reading for Linux, as it is exposed by a simple file. Not tested on MacOS. + +# Usage + +Running the program without arguments will use default values set in code. +The two first arguments set the minimum and maximum temperature of the range, the third sets the number of samples for +averaging it temperature readings and the fourth the file where temperature should be read from. + +Any other number of arguments or a number that cannot be parsed will print out the usage details. + +Pressing `Escape` will quit the application. + +# Building +## Dependencies + + - SFML + - Audio + - Window + - System + +## Sources + +`scream.ogg` is a short extract from Rick and Morty, © Adult Swim. diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..20eedb7 --- /dev/null +++ b/main.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include + +#include +#include + +// Program constants +int minRange = 35000; +int maxRange = 50000; + +int sampleCount = 20; + +std::string tempPath = "/sys/class/thermal/thermal_zone2/temp"; + +void printUsage() +{ + std::cout << "Make your computer scream when it gets hot !" << std::endl; + std::cout << "Usage :" << std::endl; + std::cout << "\tNo arguments : defaults to " << minRange/1000 << "-" << maxRange/1000 << "°C, " + << sampleCount << " samples and temperature is read from " << "\n\t\t" << tempPath << std::endl; + std::cout << "\t2 arguments : minTemp maxTemp" << std::endl; + std::cout << "\t3 arguments : minTemp maxTemp sampleCount" << std::endl; + std::cout << "\t4 arguments : minTemp maxTemp sampleCount temperatureFile" << std::endl << std::endl; + std::cout << "Temperatures are in integer °C, sampleCount is integer > 0, " + "temperatureFile is the full path to the file to read" << std::endl << std::endl; +} + +int main(int argc, char** argv) +{ + switch (argc) + { + case 5: + tempPath = argv[4]; + case 4: + try { + sampleCount = std::stoi(argv[3]); + } catch (std::exception&) { + std::cerr << "Could not convert sample count from input." << std::endl << std::endl; + printUsage(); + return -1; + } + case 3: + try { + minRange = std::stoi(argv[1])*1000; + maxRange = std::stoi(argv[2])*1000; + } catch (std::exception&) { + std::cerr << "Could not convert temperatures from input." << std::endl << std::endl; + printUsage(); + return -1; + } + case 1: + break; + default: + std::cerr << "Invalid argument count" << std::endl << std::endl; + printUsage(); + return -1; + } + + sf::SoundBuffer buffer; + if (!buffer.loadFromFile("scream.ogg")) + { + std::cerr << "Failed to open scream.ogg" << std::endl; + return -1; + } + + std::ifstream tempFile(tempPath,std::ios_base::in); + if (!tempFile.is_open()) + { + std::cerr << "Failed to open temperature data file at " << tempPath << std::endl; + return -1; + } + + // Set up the scream + sf::Sound playingSound; + playingSound.setBuffer(buffer); + playingSound.setLoop(true); + + // Set up variables + bool looping = true; + + // Initialize array to min range + int tempSamples[sampleCount]; + for (int& tempSample : tempSamples) + { + tempSample = minRange; + } + + int currentSample = 0; + int currentTemp; + + std::cout << "Starting ear damage..." << std::endl; + playingSound.play(); + + while (looping) + { + // Apparently unnecessary +// tempFile.sync(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // Rewind to read the new value + tempFile.seekg(std::istream::beg); + tempFile >> tempSamples[currentSample]; + + // Advance the index and rollover at the end of the array + currentSample = currentSample < sampleCount - 1 ? currentSample + 1 : 0; + // Compute a rolling average + currentTemp = 0; + for (int tempSample : tempSamples) + { + currentTemp += tempSample/(float)sampleCount; + } + + // Relative position of the temperature between min and max + float heatStrength = (currentTemp - minRange)/(float)(maxRange - minRange); + + // Stop the sound if low enough, restart if inside the range + if (heatStrength <= 0) + { + playingSound.stop(); + playingSound.setPitch(1); + std::cout << "Too cold, pausing ear damage." << std::endl; + continue; + } else if (playingSound.getStatus() == sf::Sound::Stopped) { + playingSound.play(); + std::cout << "Getting hot, resuming ear damage." << std::endl; + } + + playingSound.setPitch(1+0.5f*heatStrength); + playingSound.setVolume(20+80*heatStrength); + + std::cout << "Temp is " << currentTemp/1000.0 << "°C at pitch " << 1+0.5*heatStrength << " and volume " << 20+80*heatStrength << std::endl; + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) looping = false; + } + + std::cout << "Ear damage stopped." << std::endl; + + tempFile.close(); + + return 0; +} diff --git a/scream.ogg b/scream.ogg new file mode 100644 index 0000000..c806732 Binary files /dev/null and b/scream.ogg differ