欢迎光临散文网 会员登陆 & 注册

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

2023-08-28 17:01 作者:桃某桃不卷  | 我要投稿

/* 代码段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;

   }


残夏 - 霉霉 Cruel Summer - Taylor Swift c++版的评论 (共 条)

分享到微博请遵守国家法律