From 5e17568bbb23024be0ec831d0ff4d2618581faa6 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Sat, 17 Apr 2021 19:09:06 +0100 Subject: [PATCH] Basic functionnality and configuration posssible --- .gitignore | 3 ++ CMakeLists.txt | 15 ++++++ README.md | 29 ++++++++++ main.cpp | 144 +++++++++++++++++++++++++++++++++++++++++++++++++ scream.ogg | Bin 0 -> 12429 bytes 5 files changed, 191 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 main.cpp create mode 100644 scream.ogg 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 0000000000000000000000000000000000000000..c8067321f90f2434ba49e9c5b8a7d0b9c6bf0843 GIT binary patch literal 12429 zcmb_?XIN9s*61YkD&0^GRf2RW0xA$dihvjaAs}6P??oX%M5LF{QE8#0bOfX-9TAY; zL{ULO0Y$-v-wvMlob%lu_qjjres+?zXU(jcRcFoGx#Z+@1;D|-u2}aMG$gR2bZH01 z2MhG_wR7J^A}v0lP#R`R|J~5(Yh8^Y}7)toYA=U#nz)>BvE7GZ$}X z$xFUYNOu=I(Z|tbKN1p-o?`ispT2y;_Kzw+(cZmzR{4k(7~^=7KQxULM}I{w{Xz*RAb*Z9N_Q&bjz`d3bos$sU8S z9xk3p{Aq0=SbaP6n~c}gw`;H0W|;+XeKd=8v7*WL3aKG z&Y}YJFlvAoJ-m1gh^wPM8%PLx zi*y?Gp%I3lB&GE<-z1s8SVmtIsb3_UcAQTc0)k3-AgG)KdC0V+`Hm?;&^zR9jPC<^ z5*Fda=u1bU(odqdNurz}-!k>L-%;nIuLKhLBgj)`ox|?|i3;?{^S2Et=fDn904OLF zje9N1$i!7o3kCsTQuATcPG!4T$1^e^#6ZnpP66o}P(%H6VoG%4h-OKSF84%2i$rsa z#H#9DhU>*g>NndYkA~|&)^M4v&zp_vXq*E8)Hb4V#b=VqxJ9@D5GMz5l7 z3ENLzsaB`vzp;I8eZo+OnOAjT{i7=EvKyoz(OxMMBV9A+zC-4I%2~XeRWd z{IHQ$XvC2yARfDscqTN|2l_&l5HLEZ(rmjp)Bum)sLTK|nqGFJAl*=Ts3gr$d0418 z3FC%pV!NVW_m;!HrfDYM@1Z)%K0&4*@t-fjBQZb>Gf{Fnq(BSAvmFujh3N78WeY-* ze2qs7Bc$ysq@5--lqRm5es-jRbQ?@*8nBy8n|REA^RWKr@pAh5%Wu~gr>|ejyuRGz zac$<>wb_9GeIK!oBL}#oH;~k!TPLYRhxSN0DKNkUaK&fh)^s3!Bng|RiMV7sg=Ch6 zT<7)r0mMdxYCNsO4r;{m;d_>FXXQR0E!vB13o<3 zK0E_HB(9Dmj3fg{05mT1X!(i{q{&@`czmJxe9!W-Lco=)9{(r->O#5({LVu65F`o+ zNI$FlLeAj-@g@lt4j|*>>B|no=v9oV>&TpRQt9Vu%+6zEN9$uH6dYm^A~ge(D0E73 zuHImZOq?r|2jpEOMR0`*TKH_+2E#$xl4ye&%{QXGH1a)fR z5;n9B%8nlWE}t-}gd!4V(5MQn1ogrE^faZD!h}f-ir8eN=XQjE49nG^rjJX{MS?Ji zg%DHN#F{29!G5H}nC?)1I!4c>212~!$zVk5@!|=3dJ>rg>}Y=aq`EdSIt8OE+?<9< z5YCv>)04?0*ttveFW6PfLnHnoB$~M_66CcL)FD#P*@s%HVzGyutjiIZ7J64Eew%xHZj zN`5>B<0=8E`W+A6NKdcEL|+DiASxA2dNTd_Q20TinlhnqOlm_BXJp^~Z6i)$sh|*~ z2Te4C-6TaM6tQFq>vq&eEFoayW&XCMVccXgF{H5sjGIJ1Mh``TF4pvALm)I3YC~Ls zAZTn|AHp6I!3;FEAK_;34`g2h1$Uk^P(VhgpX4;*uq~!J&WAfP*~^fmWMXBWB7Bq7 z2MaXEWN32mgG$=O^fX7b6M5sWWA<4-El5|3xu@gTMv&;;Z)OiMS6G(E9&0^j3Dw+`X)lD;S z(9OyNaJ24byst`}#cPjvqy*he09qCxV}v$J5kllq^r;|;kHk10!$myOYlWPi5~NoQ zW;j3H2vQZKddT0PW!FSQ)`4o`u%{{{5Fm@`XGDvU9us+w45%NW0d?lEPiTrE*%PEb zi6d;&J1psu%k3Ft)Obpg)VWQy&!D*I#N`}>K?)U6Lq3J}BBk2|J5nN`0U2F3N!p0N z(uNiXWetBb1QO!kc|p>@)$kvMj6v~S%o~b?wU-_IqEZWvczpGj#{o#Z7}xA5NZP_B z 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