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

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