殘夏 - 霉霉 Cruel Summer - Taylor Swift c++版

/* 代碼段1 */
#pragma once
#define _PPIANO_
#include <windows.h>
#include <stdio.h>
#include <vector>
#include <string>
#include <bitset>
#include <fstream>
#include <set>
namespace PPiano
{
struct note
{
???INT8 scale;
???/*
???* scale:
???* min: -50
???* max: 43
???* specially: 127 means rest
???*/
???float beat;
};
struct key
{
???BYTE code;
???bool extended;
???uint32_t time;
???uint32_t delay;
};
class piano
{
???private: std::vector <note> score;
???private: float beatTime;
???private: INT8 initTune;
???private: bool mod;
???/*
???* false means instant while true means sustain
???*/
???/*
???* main code:
???* reset
???* read
???* compile
???* play
???*/
???public: inline void reset()
???{
??????this->beatTime = 0;
??????this->score.clear();
??????this->board.clear();
??????this->tune = 0;
??????this->mod = false;
??????this->initTune = 0;
???}
???public: inline bool read(const std::string & str)
???{
??????/*
??????* return:
??????* true means successful
??????* false means unsuccessful
??????*/
??????const size_t && settingPos = str.find("|");
??????if(settingPos == std::string::npos)
??????{
?????????fprintf(stderr, "read setting_not_found\n");
?????????return false;
??????}
??????const size_t && tunePos = str.find("tune");
??????if(tunePos == std::string::npos || tunePos > settingPos)
??????{
?????????fprintf(stderr, "read tune_setting_not_found\n");
?????????return false;?????????
??????}
??????if(str[tunePos + 4] ^ '=')
??????{
?????????fprintf(stderr, "read tune_setting_not_found\n");
?????????return false;?????????
??????}
??????const size_t && scaleLength = getScaleLength(str, tunePos + 5);
??????if(scaleLength == 0)
??????{
?????????fprintf(stderr, "read tune_setting_not_found\n");
?????????return false;??????
??????}
??????this->initTune = getScale(str.substr(tunePos + 5, scaleLength));
??????const size_t && beatTimePos = str.find("beatTime");
??????if(beatTimePos == std::string::npos || beatTimePos > settingPos)
??????{
?????????fprintf(stderr, "read beatTime_setting_not_found\n");
?????????return false;?????????
??????}
??????if(str[beatTimePos + 8] ^ '=')
??????{
?????????fprintf(stderr, "read beatTime_setting_not_found\n");
?????????return false;?????????
??????}
??????const float && beatTimeRead = std::stof(str.substr(beatTimePos + 9));
??????if(beatTimeRead < 0)
??????{
?????????fprintf(stderr, "read negative_beatTime::what():%f\n", beatTimeRead);
?????????return false;???
??????}
??????this->beatTime = beatTimeRead;
??????const size_t && instantPos = str.find("instant");
??????const size_t && sustainPos = str.find("sustain");
??????if((~instantPos && ~sustainPos) || (instantPos != std::string::npos && sustainPos != std::string::npos))
??????{
?????????fprintf(stderr, "read instant_and_sustain_setting_not_found\n");
?????????return false;????????????
??????}
??????this->mod = instantPos == std::string::npos;
??????/*
??????* by here is for setting
??????*/
??????const size_t && length = str.length();
??????float beatNow = 0.0f, beatBegin = -1.0f, beatEnd = -1.0f, speed = 1.0f;
??????std::bitset <10> used, start;
??????std::set <uint8_t> pass[10];
??????for(size_t i = settingPos + 1; i ^ length; ++ i)
??????{
?????????switch(str[i])
?????????{
????????????case '!': /* rest */
???????????????if(true)
???????????????{
??????????????????const size_t && beatLength = getBeatLength(str, i + 1);
??????????????????float beat = getBeat(str.substr(i + 1, beatLength));
??????????????????if(beatBegin <= beatNow && beatNow < beatEnd) /* speed */
??????????????????{
?????????????????????const float temp = beat;
?????????????????????beat /= 1.0f - (beat - beatBegin) / (beatEnd - beatBegin) * (1.0f - speed); /* gradually */
?????????????????????beatNow += temp;
??????????????????}
??????????????????else
??????????????????{
?????????????????????beatNow += beat;
?????????????????????speed = 1.0f;
??????????????????}
??????????????????i += beatLength;
??????????????????this->score.push_back({127, beat});
???????????????}
???????????????break;
????????????case '@': /* teleport target */
???????????????if(!isdigit(str[i + 1]))
???????????????{
??????????????????fprintf(stderr, "read unknown_keyword::what():%c ::at():%u\n", str[i + 1], i);
??????????????????return false;
???????????????}
???????????????start[str[i + 1] ^ 48] = true;
???????????????++ i;??????????????????
???????????????break;
????????????case '%': /* end */
???????????????if(true)
???????????????{
??????????????????if(!isdigit(str[i + 1]))
??????????????????{
?????????????????????fprintf(stderr, "read unknown_keyword::what():%c ::at():%u\n", str[i + 1], i);
?????????????????????return false;
??????????????????}
??????????????????const UINT8 && ord = str[i + 1] ^ 48;
??????????????????if(used[ord] == true)
??????????????????{
?????????????????????const char temp[] = {'$', str[i + 1], 0};
?????????????????????size_t telePos = str.find(temp);
?????????????????????i = telePos + 1;
??????????????????}
??????????????????else
??????????????????{
?????????????????????++ i;
??????????????????}??????
???????????????}
???????????????break;
????????????case '$': /* loop */
???????????????if(true)
???????????????{
??????????????????if(!isdigit(str[i + 1]))
??????????????????{
?????????????????????fprintf(stderr, "read unknown_keyword::what():%c ::at():%u\n", str[i + 1], i);
?????????????????????return false;
??????????????????}
??????????????????const UINT8 && ord = str[i + 1] ^ 48;
??????????????????for(uint8_t j = 0; j ^ 10; ++ j)
??????????????????{
?????????????????????if(start[j] && j ^ ord)
?????????????????????{
????????????????????????pass[j].insert(ord);
?????????????????????}
??????????????????}
??????????????????start[ord] = false;
??????????????????if(used[ord] == false)
??????????????????{
?????????????????????used[ord] = true;
?????????????????????for(auto && it : pass[ord])
?????????????????????{
????????????????????????used[it] = false;
?????????????????????}
?????????????????????const char temp[] = {'@', str[i + 1], 0};
?????????????????????size_t telePos = str.find(temp);
?????????????????????i = telePos == std::string::npos ? settingPos : telePos + 1;
??????????????????}
??????????????????else
??????????????????{
?????????????????????++ i;
??????????????????}
???????????????}
???????????????break;
????????????case '~': /* speed control */
???????????????if(true)
???????????????{
??????????????????size_t * posPtr = new size_t;
??????????????????const float && speedRead = std::stof(str.substr(i + 1), posPtr);
??????????????????i += * posPtr + 1;
??????????????????if(speedRead < 0)
??????????????????{
?????????????????????fprintf(stderr, "read nagative_times::what():%f\n", speedRead);
?????????????????????return false;
??????????????????}
??????????????????const size_t && beatLength = getBeatLength(str, i);
??????????????????const float && beat = getBeat(str.substr(i, beatLength));
??????????????????i += beatLength;
??????????????????-- i;
??????????????????beatBegin = beatNow;
??????????????????beatEnd = beatNow + beat;
??????????????????speed = speedRead;
???????????????}
???????????????break;
????????????default:
???????????????if(isalpha(str[i])) /* note */
???????????????{
??????????????????const size_t && scaleLength = getScaleLength(str, i);
??????????????????const INT8 && scale = getScale(str.substr(i, scaleLength));
??????????????????i += scaleLength;
??????????????????const size_t && beatLength = getBeatLength(str, i);
??????????????????float beat = getBeat(str.substr(i, beatLength));
??????????????????if(beatBegin <= beatNow && beatNow < beatEnd) /* speed */
??????????????????{
?????????????????????const float temp = beat;
?????????????????????beat /= 1.0f + (beatEnd - beatNow) / (beatEnd - beatBegin) * (speed - 1.0f); /* gradually */
?????????????????????beatNow += temp;??????
??????????????????}
??????????????????else
??????????????????{
?????????????????????beatNow += beat;
?????????????????????speed = 1.0f;
??????????????????}
??????????????????i += beatLength;
??????????????????-- i;
??????????????????this->score.push_back({scale, beat});???
???????????????}
???????????????else if(!isspace(str[i]))
???????????????{
??????????????????fprintf(stderr, "read unknown_keyword::what():%c ::at():%u\n", str[i], i);
??????????????????return false;
???????????????}
?????????} /* switch */
??????} /* for */
??????return true;
???} /* read */
???private: static size_t getScaleLength(const std::string & str, const size_t & begin)
???{???
??????/* return 0 means unsuccessful */
??????const size_t && length = str.length();
??????if(begin >= length)
??????{
?????????fprintf(stderr, "getScaleLength out_of_range()::what():%u\n", begin);
?????????return 0;?????????
??????}
??????if(!isalpha(str[begin]))
?????????return 0;
??????if(!isdigit(str[begin + 1]) && !(str[begin + 1] == '#') && !(str[begin + 1] == '?'))
?????????return 1;
??????if(!isdigit(str[begin + 2]) && !(str[begin + 2] == '#') && !(str[begin + 2] == '?'))
?????????return 2;
??????return 3;
???}
???private: static INT8 getScale(const std::string && str)
???{???
??????/* return 127 means unsuccessful */
??????INT8 scaleCode = 0;
??????bool ableToUp = true, ableToDown = true;
??????const size_t && length = str.length();
??????if(length > 3 || length == 0)
??????{
?????????fprintf(stderr, "getScale not_found::what():%s\n", str.c_str());
?????????return 127;????????????
??????}
??????switch(str[0])
??????{
?????????case 'C':
?????????case 'c':
????????????scaleCode = -21 - (bool)isupper(str[0]) * 12;
????????????ableToDown = false;
????????????break;
?????????case 'D':
?????????case 'd':
????????????scaleCode = -19 - (bool)isupper(str[0]) * 12;
????????????break;
?????????case 'E':
?????????case 'e':
????????????scaleCode = -17 - (bool)isupper(str[0]) * 12;
????????????ableToUp = false;
????????????break;
?????????case 'F':
?????????case 'f':
????????????scaleCode = -16 - (bool)isupper(str[0]) * 12;
????????????ableToDown = false;
????????????break;
?????????case 'G':
?????????case 'g':
????????????scaleCode = -14 - (bool)isupper(str[0]) * 12;
????????????break;
?????????case 'A':
?????????case 'a':
????????????scaleCode = -12 - (bool)isupper(str[0]) * 12;
????????????break;
?????????case 'B':
?????????case 'b':
????????????scaleCode = -10 - (bool)isupper(str[0]) * 12;
????????????ableToUp = false;
????????????break;
?????????default:
????????????fprintf(stderr, "getScale not_found::what():%s\n", str.c_str());
????????????return 127;?????????
??????} /* switch */
??????if(length > 1)
??????{
?????????switch(str[1])
?????????{
????????????case '#':
???????????????if(ableToUp)
???????????????{
??????????????????++ scaleCode;
???????????????}
???????????????else
???????????????{
??????????????????fprintf(stderr, "getScale disable_up::what():%s\n", str.c_str());
??????????????????return 127;???????????????
???????????????}
???????????????break;
????????????case '?':
???????????????if(ableToDown)
???????????????{
??????????????????-- scaleCode;
???????????????}
???????????????else
???????????????{
??????????????????fprintf(stderr, "getScale disable_down::what():%s\n", str.c_str());
??????????????????return 127;???????????????
???????????????}
???????????????break;
????????????default:
???????????????if(isdigit(str[1]) && str[1] <= '5')
???????????????{
??????????????????INT8 times = str[1] ^ 48;
??????????????????if(isupper(str[0]))
??????????????????{
?????????????????????times = -times;
??????????????????}
??????????????????scaleCode += times * 12;
???????????????}
???????????????else
???????????????{
??????????????????fprintf(stderr, "getScale not_found::what():%s\n", str.c_str());
??????????????????return 127;??????????????????
???????????????}
?????????} /* switch */
??????} /* if */
??????if(length > 2)
??????{
?????????if(str[1] == '#' || str[1] == '?')
?????????{
????????????if(isdigit(str[2]) && str[2] <= '5')
????????????{
???????????????INT8 times = str[2] ^ 48;
???????????????if(isupper(str[0]))
???????????????{
??????????????????times = -times;
???????????????}
???????????????scaleCode += times * 12;
????????????}
????????????else
????????????{
???????????????fprintf(stderr, "getScale not_found::what():%s\n", str.c_str());
???????????????return 127;??????????????????
????????????}?????????
?????????}
?????????else
?????????{
????????????switch(str[2])
????????????{
???????????????case '#':
??????????????????if(ableToUp)
??????????????????{
?????????????????????++ scaleCode;
??????????????????}
??????????????????else
??????????????????{
?????????????????????fprintf(stderr, "getScale disable_up::what():%s\n", str.c_str());
?????????????????????return 127;???????????????
??????????????????}
??????????????????break;
???????????????case '?':
??????????????????if(ableToDown)
??????????????????{
?????????????????????-- scaleCode;
??????????????????}
??????????????????else
??????????????????{
?????????????????????fprintf(stderr, "getScale disable_down::what():%s\n", str.c_str());
?????????????????????return 127;???????????????
??????????????????}
??????????????????break;
???????????????default:
??????????????????fprintf(stderr, "getScale not_found::what():%s\n", str.c_str());
??????????????????return 127;????????????????????????????????????
????????????} /* switch */
?????????} /* else */
??????} /* if */
??????if(scaleCode < minTone || scaleCode > maxTone)
??????{
?????????fprintf(stderr, "getScale out_of_range::what():%s\n", str.c_str());
?????????return 127;????????????
??????}
??????return scaleCode;
???} /* getScale */
???private: static size_t getBeatLength(const std::string & str, const size_t & begin)
???{
??????const size_t && length = str.length();
??????size_t i = begin;
??????for(; i ^ length; ++ i)
??????{
?????????if(str[i] != '-' && str[i] != '_' && str[i] != '=' && str[i] != '.' && str[i] != '*' && str[i] != '/' && !isdigit(str[i]))
?????????{
????????????break;
?????????}
??????}
??????return i - begin;
???}