同學整活系列:C++版《青花瓷》留給音樂區(qū)的樂器不多了

#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);
??????}
};