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

同学整活系列:C++版《青花瓷》留给音乐区的乐器不多了

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

#pragma once

#ifndef _PMUSIC_

#define _PMUSIC_

#endif


#include <windows.h>

#include <math.h>

#include <vector>

#include <string>

#include <stdio.h>

#include <fstream>


struct note

{

   float scale;

   float time;

};


class music

{

   public:

      std::vector <note> score;


      music()

      {

      }


      music(const std::vector <note> && base)

      {

         this->score = base;

      }


      void clear()

      {

         this->score.clear();

      }


      void read(const float && pitch, const float && unit, std::string str)

      {

         size_t cnt = 0;

         float base = 0, scale = 0;

         bool rest = false;


         while(true)

         {

            const size_t && length = str.size();

            size_t && begin = ~0ul, end = length;


            for(size_t i = 0; i ^ length; ++ i)

               if(!isspace(str[i]))

               {

                  begin = i;

                  break;

               }


            if(begin == ~0ul)

               break;


            for(size_t i = begin; i ^ length; ++ i)

               if(isspace(str[i]))

               {

                  end = i;

                  break;

               }         


            if(cnt % 3 == 0)

            {

               base = stof(str.substr(begin, end - begin));

            }

            else if(cnt % 3 == 1)

            {

               const std::string && temp = str.substr(begin, end - begin);


               if(temp == "do")

                  scale = 0.0f;

               else if(temp == "do#")

                  scale = 1.0f;

               else if(temp == "re")

                  scale = 2.0f;

               else if(temp == "re#")

                  scale = 3.0f;

               else if(temp == "mi")

                  scale = 4.0f;

               else if(temp == "fa")

                  scale = 5.0f;

               else if(temp == "fa#")

                  scale = 6.0f;

               else if(temp == "sol" || temp == "so")

                  scale = 7.0f;

               else if(temp == "sol#" || temp == "so#")

                  scale = 8.0f;

               else if(temp == "la")

                  scale = 9.0f;

               else if(temp == "la#")

                  scale = 10.0f;

               else if(temp == "si" || temp == "ti")

                  scale = 11.0f;

               else if(temp == "rest")

                  rest = true;

               else

                  scale = stof(temp);

            }

            else

            {            

               if(rest)

                  this->score.push_back({0, unit * stof(str.substr(begin, end - begin))});

               else

                  this->score.push_back({base * 12.0f + scale - 9.0f + pitch, unit * stof(str.substr(begin, end - begin))});


               base = 0;

               scale = 0;

               rest = false;

            }


            ++ cnt;

            str.erase(0, end);

         }

      }


      void read(const float && pitch, const float && unit, std::ifstream & stream)

      {

         std::string str;


         size_t cnt = 0;

         float base = 0, scale = 0;

         bool rest = false;


         while(true)

         {

            stream >> str;      


            if(stream.eof() || str == "end")

               break;


            if(cnt % 3 == 0)

            {

               base = stof(str);

            }

            else if(cnt % 3 == 1)

            {

               if(str == "do")

                  scale = 0.0f;

               else if(str == "do#")

                  scale = 1.0f;

               else if(str == "re")

                  scale = 2.0f;

               else if(str == "re#")

                  scale = 3.0f;

               else if(str == "mi")

                  scale = 4.0f;

               else if(str == "fa")

                  scale = 5.0f;

               else if(str == "fa#")

                  scale = 6.0f;

               else if(str == "sol" || str == "so")

                  scale = 7.0f;

               else if(str == "sol#" || str == "so#")

                  scale = 8.0f;

               else if(str == "la")

                  scale = 9.0f;

               else if(str == "la#")

                  scale = 10.0f;

               else if(str == "si" || str == "ti")

                  scale = 11.0f;

               else if(str == "rest")

                  rest = true;

               else

                  scale = stof(str);            

            }

            else

            {

               if(rest)

                  this->score.push_back({0, unit * stof(str)});

               else

                  this->score.push_back({frequency(base * 12.0f + scale - 9.0f + pitch), unit * stof(str)});


               base = 0;

               scale = 0;

               rest = false;               

            }


            ++ cnt;

         }

      }


      void run()

      {

         for(const note & i : this->score)

         {

            //printf("frequency : %f time : %f\n", frequency(i.scale), i.time);


            Beep(i.scale, i.time);

         }

      }


   protected:

      inline static float frequency(const float & scale)

      {

         return 27.5f * powf(2.0f, (scale + 48.0f) / 12.0f);

      }

};

同学整活系列:C++版《青花瓷》留给音乐区的乐器不多了的评论 (共 条)

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