Virtual piano automatically plays music scores

Source: Internet
Author: User
Tags sendmsg
Piano Key Distribution

Piano has a total of 88 keys, 52 white keys, and 36 black keys.

It is divided

Bass: incomplete big-two-character group, big-character group, and big-character group;

Central audio area: Small character group, small character group, and small character group;

Tweeting area: three groups of small characters, four groups of small words, and incomplete five groups of small words.

Except for Group A, Group # A, and group B, group C only has one voice.

The other groups have 12 audios: C, # C, D, # D, E, F, # F, G, # G, A, # A, and B.

Flash piano games

There is a flash game on the Internet.KeyboardBulletPiano, Match the keys on the keyboard with the piano, for example:

 

Game site: http://www.hao352.com/tangangqin.htm

The starting point of this game is to make the piano popular and simple. The principle is as follows:/// // <Br/> // low Section <br/> // 1_2_3_4_5_6_7 _ <br/> // abcdefg </P> <p> // middle section <br/>/ /1-2-3-4-5-6-7-<br/> // hijklmn </P> <p> // high section <br/> // 1'2' 4 '5' 7' <br/> // opqrstu <br/> ////////////// ////////////////////

AboveConversion table, There are three numeric suffixes:

  • '_'Indicates the bass segment
  • '-'Indicates the audio segment
  • '`'Indicates the treble

A score based on this encoding is as follows:

Blue and white porcelain flash keyboard piano score </P> <p> LLJ ijf ijlj I <br/> LLJ ije ijli H <br/> hijlmlj ljji I <br/> HIH IHI ijlj <br/> LLJ ijf ijlji <br/> LLJ ije ijlih <br/> hij lmlj ljjii ejiih <br/>

Players canEncoding, Press the corresponding button to play a song ~

 

Principle Analysis

First, to make such a game, we need a MIDI voice engine:CodeprojectWe found a good open-source MIDI engine: midiwrapper.

URL: http://www.codeproject.com/kb/audio-video/midiwrapper.aspx. The author implements a standard piano keyboard.

Then, the music score is converted into corresponding notes. Music score is a string of characters.Conversion table, Which is converted to a bass, median, or tweeter note. How can this problem be implemented in the code?

Cmidiwrapper defines 12 basic sounds in the piano,

Enum note_id {C, c_sharp, D, d_sharp, E, F, f_sharp, G, g_sharp, A, <br/> a_sharp, B}; <br/>

Sharp represents a high half tone, but we usually use seven notes:1, 2, 3, 4, 5, 6, 7 <=> C, D, E, F, G, a B.

Note_per_octave = 12, // a group of 12 voices
Low_note = 36 // The start value of the low note.

Noteid = (octave) * note_per_octave + low_note;

Ave ave indicates the number of audio groups. There are five groups from 0 to 4. There are five levels from the bass to the top, and note_per_octave is an offset.We are concerned with the extraction of C, D, E, F, G, A, and B in each audio group.

Code:

# Include "stdafx. H "</P> <p> # include <iostream> <br/> # include <sstream> <br/> # include <fstream> <br/> # include <string> <br/> # include <vector> <br/> # include <map> <br/> # include <ctime> <br/> # include <xutility> <br/> # include <algorithm> <br/> # include <windows. h> </P> <p> # include "Midi. H "<br/> # include" midioutdevice. H "<br/> # include" shortmsg. H "</P> <p> using namespace STD; <br/> using MIDI: cmidioutdevice; <Br/> using MIDI: cshortmsg; </P> <p> // some useful constants <br/> const unsigned char channel = 0; <br/> const unsigned char note_id = 64; <br/> const unsigned char velocity = 127; </P> <p> class musicplayer <br/> {<br/> Public: <br/> musicplayer (MIDI: cmidioutdevice * Device) <br/>: _ DEVICE <br/>{< br/> m_keymap [0] = C; // <br/> m_keymap [1] = D; // <br/> m_keymap [2] = E; // <br/> m_keymap [3] = f; // <br/> M_keymap [4] = g; // <br/> m_keymap [5] = A; // <br/> m_keymap [6] = B; // <br/>}</P> <p> ~ Musicplayer () <br/>{< br/> _ DEVICE = 0; <br/>}</P> <p> Enum note_information <br/> {<br/> channel = 0, <br/> note_id = 64, <br/> velocity = 127, <br/> note_per_octave = 12, // one syllable <br/> low_note = 36 <br/> }; </P> <p> Enum note_id {C, c_sharp, D, d_sharp, E, F, f_sharp, G, g_sharp, A, <br/> a_sharp, B }; </P> <p> void playlatterrhythm (const unsigned char & letter, float time) <br/>{< br/> unsigned char noteid = lett Ertonote (letter); </P> <p> onnoteon (noteid); <br/>{< br/> // wait a bit <br/> :: sleep (700 * time); <br/>}onnoteoff (noteid); <br/>}</P> <p> // Postfix :_, -<br/> void playnumberrhythm (INT number, unsigned char Postfix, float time) <br/>{< br/> unsigned char noteid = numbertonote (number, postfix ); </P> <p> onnoteon (noteid); <br/>{< br/> // wait a bit <br/> //:: sleep (700 * time); <br/> clock_t current = clock (); </P> <P> while (clock ()-current <700 * Time) <br/>; </P> <p>} onnoteoff (noteid ); <br/>}</P> <p> protected: </P> <p> // note-on Event Notification <br/> bool onnoteon (unsigned char noteid) <br/>{< br/> MIDI: cshortmsg shortmsg (MIDI: note_on, channel, noteid, velocity, 0); <br/> shortmsg. sendmsg (* _ device); </P> <p> return true; <br/>}</P> <p> // note-Off Event Notification <br/> bool onnoteoff (unsigned char noteid) <br/> {< Br/> MIDI: cshortmsg shortmsg (MIDI: note_off, channel, noteid, velocity, 0); <br/> shortmsg. sendmsg (* _ device); </P> <p> return true; <br/>}</P> <p> //////////////////////////// /// // <br/> // low section <br/> // 1_2_3_4_5_6_7 _ <br/> // abcdefg </P> <p> // middle section <br/> // 1-2-3-4-5-6-7-<br/> // hijklmn </P> <p> // High Section <br/> // 1'2' 3' 4'5' 6'7' <br/> // opqrstu <br/> // <Br/> unsigned char lettertonote (unsigned char letter) <br/> {<br/> bool result; <br/> result = <br/> (letter> = 'A' & letter <= 'Z ') | <br/> (letter> = 'A' & letter <= 'Z'); </P> <p> If (! Result) <br/> return result; </P> <p> int octave (0); <br/> int idx (-1 ); </P> <p> If (letter> = 97) <br/> {<br/> Ave ave = (letter-'A')/7; <br/> idx = (letter-'A') % 7; <br/>}< br/> else <br/> {<br/> Ave ave = (letter-'A')/7; <br/> idx = (letter-'A') % 7; <br/>}</P> <p> int noteid (-1 ); </P> <p> noteid = m_keymap [idx]; <br/> noteid + = (Ave ave + 1) * note_per_octave + low_note; </P> <p> return noteid; <br/>}</P> <p> // postf IX: '_ ''-''' <br/> // lowmiddle high </P> <p> // Number: 1-7 <br/> unsigned char numbertonote (INT number, unsigned char postfix) <br/>{< br/> int octave (-1 ); <br/> int noteid (-1); </P> <p> If ('_' = postfix) <br/> octave = 0; <br/> else if ('-' = postfix) <br/> Ave ave = 1; <br/> else if (''' = postfix) <br/> octave = 2; </P> <p> noteid = m_keymap [number-1]; <br/> noteid + = (octave + 1) * note_per_octave + low_note; </P> <p> retu Rn noteid; <br/>}</P> <p> PRIVATE: <br/> MIDI: cmidioutdevice * _ device; <br/> intm_keymap [7]; <br/>}; </P> <p> int main (void) <br/>{< br/> try <br/> {<br/> // make sure there is an output device present <br/> If (cmidioutdevice :: getnumdevs ()> 0) <br/>{< br/> cmidioutdevice outdevice; </P> <p> // use the first device <br/> outdevice. open (0); </P> <p> musicplayer player (& outdevice); </P> <p> // ifstream infile ("BJ welcom U-letter.txt "); <br/> // vector <string> musiclist; <br/> // copy (istream_iterator <string> (infile), istream_iterator <string> (), back_inserter (musiclist); <br/> // copy (musiclist. begin (), musiclist. end (), ostream_iterator <string> (cout, "/N"); <br/> // For (size_t I (0 ); I <musiclist. size (); I ++) <br/> // {<br/> // STD: istringstream ISS (musiclist [I]); <br/> // unsigned char letter; <br/> // unsigned char U; <Br/> // float value; <br/>/ISS> letter> U> value; <br/> // STD :: cout <letter <"/t" <value <STD: Endl; <br/> // player. playlatterrhythm (letter, value); <br/>/}</P> <p> // ifstream infile ("BJ welcom U-number.txt "); <br/> ifstream infile ("Tian Kong Zhi cheng.txt"); </P> <p> vector <string> musiclist; <br/> copy (istream_iterator <string> (infile), istream_iterator <string> (), back_inserter (musiclist )); <Br/> copy (musiclist. begin (), musiclist. end (), ostream_iterator <string> (cout, "/N"); </P> <p> for (size_t I (0); I <musiclist. size (); I ++) <br/>{< br/> If ('#' = musiclist [I] [0]) <br/> continue; </P> <p> STD: istringstream ISS (musiclist [I]); <br/> int number; <br/> unsigned char Postfix; <br/> float value; <br/> ISS> number> Postfix> value; <br/> STD :: cout <number <"/t" <value <STD: Endl; <br/> play Er. playnumberrhythm (number, Postfix, value); <br/>}</P> <p> // close device <br/> outdevice. close (); <br/>}< br/> else <br/>{< br/> STD: cout <"No MIDI output devices present! /N "; <br/>}< br/> catch (const STD: exception & ERR) <br/>{< br/> STD :: cout <err. what (); <br/>}</P> <p> system ("pause"); </P> <p> return 0; <br/>}< br/>

To run the code, download cmidiwrapper:

This library uses the cwinthread under MFC, so you need to add the following in stdafx:

# DEFINE _ afxdll
# Include <afxwin. h>
In addition, the project is set to use a multi-byte character set. In C ++ code generation, the Runtime Library is multi-threaded dll/MD, and the input library winmm. Lib is added.

Program description

The playlatterrhythm function can play letters and notes. Float indicates the pause time,

Playnumberrhythm plays a digital note, with a suffix indicating the pitch, medium, and low. Float indicates the pause time.

Finally, based on the letter and syllable in Flash, I made my piano profile,

Letter ProfileFormat:Letter, playtime

Digital ProfileIn the following format:

Number_playtimeNumber-PlaytimeNumber 'playtime

BJ welcom U-letter.txt content, just Beijing Huan drink your first sentence:

J, 0.5l, 0.5j, 0.5i, 0.5j, 0.5i, 0.5j, 1j, 0.75i, 0.25f, 0.5 h, 0.5j, 0.5i, 1.5 <br/>

 

BJ welcom U-number.txt content, Beijing Huan drink your whole profile, digital version:

# Sentence1 <br/> latency 2-1.5 <br/> # sentence2 <br/> latency <br/> # sentene3 <br/> latency <br/> # sentence4 <br /> 2-0.53-0.52-0.51-0.55-0.756-0.253-16_0.53-0.52-0.52-0.51-1.5 <br/> # sentence5 <br/> 3-0.55-0.51 '0. 55-0.56-1.55-0.56-0.55-0.53-0.53-0.55-0.55-1.5 <br/> # sentence6 <br/> 3-0.55-0.56-0.51 '0. 52 '0. 51 '0. 55-0.53-0.52-0.55-1.53-2

When you run the program, the system automatically plays the created profile ~O (∩) O Haha ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.