Page 1 of 2 [ 18 posts ]  Go to page 1, 2  Next

ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

14 Apr 2007, 2:27 am

I am writing a program to play One Winged Angel, through the PC speaker. I've finished setting up the framework and now I'm working on playing the music.

Here is my framework:

play.h

Code:
/*
 *  play.h
 * 
 *
 *  Created by Aaron Hayes on 3/27/07.
 *  Copyright 2007 Aaron Hayes. All rights reserved.
 *
 */
#ifndef _PLAY_H_
#define _PLAY_H_
#include <iostream>
#include <windows.h>

using std::cin;
using std::cout;
using std::endl;

class Play;

class Beat
{
   friend Play& operator<<(Play& pin, Beat* beat);
private:
   int m_nFract;
public:
   /*
   Use the following in this function:
   WHOLE
   HALF
   QUATER
   EIGHTH
   SIXTEENTH
   use in the form of play << ... << play.fractional(HALF) << ...
   remember you must specify BPM with setBPM first
   */
   static Beat* change(int newBeat);
};

class Play
{
private:
   //current length and note multipliers
   int m_nLength;
   int m_nBPM;
   float m_fMult;
public:
   //user accessible constants
   float C[9];
   //member functions
   Play();
   int OnConv(char note);
   void OnPlay(char *notes, int length);
   void OnTwinkle();
   void OnUserPlay();
   void OnWowWow();
   friend Play& operator<<(Play& pin, char *notes);
   friend Play& operator<<(Play& pin, int length);
   friend Play& operator<<(Play& pin, float mult);
   friend Play& operator<<(Play& pin, double mult);
   friend Play& operator<<(Play& pin, Beat* beat);
   //special note: this must be done BEFORE specifying fractional notes
   void setBPM(int BPM);
};

#define WHOLE 1
#define HALF 2
#define QUARTER 4
#define EIGHTH 8
#define SIXTEENTH 16

Play& operator<<(Play& pin, char *notes);
Play& operator<<(Play& pin, int length);
Play& operator<<(Play& pin, float mult);
Play& operator<<(Play& pin, Beat* beat);

#endif


play.cpp
Code:
/*
 *  play.cpp
 * 
 *
 *  Created by Aaron Hayes on 3/27/07.
 *  Copyright 2007 Aaron Hayes. All rights reserved.
 *
 */

#include "play.h"

Beat* Beat::change(int newBeat)
{
   Beat *beat = new Beat;
   beat->m_nFract=newBeat;
   return beat;
}

Play::Play()
{
   this->m_fMult=1;
   this->m_nLength=100;
   this->C[0] = 0.0625;
   this->C[1] = 0.125;
   this->C[2] = 0.25;
   this->C[3] = 0.5;
   this->C[4] = 1.0;
   this->C[5] = 2.0;
   this->C[6] = 4.0;
   this->C[7] = 8.0;
   this->C[8] = 16.0;
   this->m_nBPM=100;
}
int Play::OnConv(char note)
{
   switch(note)
   {
   case 'c':
      return (int)((float)262*this->m_fMult);
   case 'd':
      return (int)((float)294*this->m_fMult);
   case 'e':
      return (int)((float)330*this->m_fMult);
   case 'f':
      return (int)((float)349*this->m_fMult);
   case 'g':
      return (int)((float)392*this->m_fMult);
   case 'a':
      return (int)((float)440*this->m_fMult);
   case 'b':
      return (int)((float)494*this->m_fMult);
   default:
      return 32767;
   }
}

void Play::OnPlay(char *notes, int length)
{
   int i = 0;
   while(notes[i]!=0)
   {
      Beep(OnConv(notes[i]), length);
      i++;
   }
}

void Play::OnTwinkle()
{
   char a[50] = "c c g g a a g  f f e e d d c  ";
   char b[50] = "f f e e d d c  ";
   OnPlay(a, 100);
   OnPlay(b, 100);
   OnPlay(b, 100);
   OnPlay(a, 100);
}

void Play::OnUserPlay()
{
   while(1){
      char sMusic[500];
      cout << "Enter notes (c d e f g a b), using spaces to pause: ";
      cin.getline(sMusic, 500);
      OnPlay(sMusic, 100);
      cout << "Play again? (y/n): ";
      cin >> sMusic;
      if(sMusic[0] != 'y')
         break;
      cin.get();
   }
}

void Play::OnWowWow()
{
   char *p = "cdefgabagfedc";
   for(int i = 0; i < 20; i++)
      OnPlay(p, 20);
}

void Play::setBPM(int BPM)
{
   if(BPM > 0)
      this->m_nBPM=BPM;
}

/*
   if(fraction <=0)
      return *this;
   int duration = 60*1000;
   duration/=this->m_nBPM;
   duration/=fraction;
   this->m_nLength=duration;
   return *this;
*/
Play& operator<<(Play& pin, char *notes)
{
   pin.OnPlay(notes, pin.m_nLength);
   return pin;
}

Play& operator<<(Play& pin, int length)
{
   pin.m_nLength = length;
   return pin;
}
Play& operator<<(Play& pin, float mult)
{
   pin.m_fMult=mult;
   return pin;
}
Play& operator<<(Play& pin, double mult)
{
   pin.m_fMult=(float)mult;
   return pin;
}
Play& operator<<(Play& pin, Beat* beat)
{
   if(beat->m_nFract <= 0)
      return pin;
   int duration = 60*1000;
   duration/=pin.m_nBPM;
   duration/=beat->m_nFract;
   pin.m_nLength=duration;
   delete beat;
   return pin;
}


main.cpp
Code:
#include "play.h"

void main()
{
   Play play;
   play.setBPM(135);
   play << Beat::change(WHOLE);
#define C1 play.C[1]
#define C2 play.C[2]
#define C3 play.C[3]
#define C4 play.C[4]
#define C5 play.C[5]
#define HHALF Beat::change(HALF)
#define HHOLE Beat::change(WHOLE)
#define QUART Beat::change(QUARTER)
   //1
   play << C4 << "gcgc" << "gcgc" << C5 << HHALF
      << "de" << QUART << "fe" << HHALF
      << "dedfe";
   //4
   play << "de" << QUART << "fe" << HHALF
      << "dedfe" << HHOLE << C4 << "gcgc" << "gcgc";
   //7
   play << HHALF << "b" << C5 << "c" << QUART
      << "dc" << HHALF << C4 << "b" << C5 << "c" << C4 << "b"
      << C5 << "dc" << "b" << C5 << "c" << QUART
      << "dc" << HHALF << C4 << "b" << C5 << "c" << C4 << "b"
      << C5 << "dc";
   //9
   play << C4 << "c" << C5 << "c" << C4 << "bbaagf"
      << "cfeeddc" << C3 << "b" << HHOLE << C4 << "gcgc";
   //12
   play << "gcgc" << "gcgc" << "gcgc" << "gcgc";
   //16
   play << "gcgg" << C5 << "c" << HHALF << "ccc" << HHOLE
      << C4 << "b" << HHALF << "bbb" << HHOLE << "a"
      << HHALF << "ggg" << HHOLE << "g" << HHALF
      << "fff" << HHOLE << "f" << HHALF << "eee" << HHOLE
      << "d" << HHALF << "ddd";
   //20
   play << HHOLE << "c" << HHALF << "ccc" << C3
      << HHOLE << "b" << C4 << HHALF << "ccd" << QUART
      << "egb" << C5 << "f" << HHOLE << "e" << QUART << C4
      << "cegb" << C5 << HHALF << "c" << QUART << "de"
      << HHALF << "fgfe" << "dd" << C4 << "ba";
   //23
   play << HHOLE << "b" << HHALF << "agf" << C5 << "ddc" << C4
      << HHOLE << "b"   << HHALF << "efgdeg" << HHOLE << "gggg";
   //26
   play << "gggg" << "gg" << C3 << "aa";
   //28
   play << HHALF << "b" << C4 << "f" << C3 << "b" << C4 << "f"
      << C3 << "b" << C4 << "f" << C3 << "b" << C4 << "f"
      << C3 << "b" << C4 << "f" << C3 << "b" << C4 << "f"
      << C3 << "b" << C4 << "f" << C3 << "b" << C4 << "f";
   //30
   play << C3 << "b" << C4 << "f" << C3 << "b" << C4 << "f"
      << C3 << "b" << C4 << "f" << C3 << "b" << C4 << "f"
      << C3 << "b" << C4 << "f" << C3 << "b" << C4 << "f"
      << C3 << "b" << C4 << "f" << C3 << "b" << C4 << "f";
   //32
   play << C3 << "bbbbbbbb" << "bbbbbbbb" << "bbbbbbbb";
   //35
   play << "bbbbbbbb" << "bbbbbbbb" << "bbbbbbbb";
   //38
   play << "bbbbbbbb" << "bbbbbbb" << C4 << "e" << C5 << "bbbb"
      << C4 << "ffgb";
   //42
   play << HHOLE << "bb" << HHALF << "bb" << HHOLE << "b" << HHALF
      << "bb" << HHOLE << "b" << HHALF << "bb" << HHOLE << "b"
      << "bb" << HHALF << "bb" << HHOLE << "b" << HHALF << "bb"
      << HHOLE << "b" << HHALF << "bb" << HHOLE << "b" << C5
      << HHALF << "dc" << HHOLE << C4 << "b" << HHALF << " fff";
   //47
   play << "eegg" << HHOLE << "f" << HHALF << "eg" << C5 << "dc" << C4
      << HHOLE << "b" << HHALF << " fff" << "eegg" << HHOLE << "f"
      << HHALF << "eg" << HHOLE << "bfbf";
   //51
   play << HHALF << "bfab" << "bfab" << HHOLE << "bfbf" << HHALF << "bfab"
      << "bfab" << C5 << "dc" << C4 << HHOLE << "b" << HHALF << " fff" << "ee";
   //55
   play << "gg" << HHOLE << "f" << HHALF << "egde" << HHOLE << "eeee";
   //57
   play << "eeee" << "f" << C5 << "c" << C4 << "f" << C5 << "c" << C4
      << "f" << C5 << "c" << C4 << "f" << C5 << "c" << C4;
   //60
   play << "f" << C5 << "c" << C4 << "f" << C5 << "c" << C4 << "f" << C5
      << "c" << C4 << "f" << C5 << "c" << C4 << "f" << C5 << "c" << C4
      << "f" << C5 << "c" << C4 << "f" << C5 << "c" << C4 << "f" << C5
      << "c" << C4<< "f" << C5 << "c" << C4<< "f" << C5 << "c" << C4;
   //65
   play << "f" << C5 << "c" << C4 << "fa" << QUART << "b" << C5 << "fdf"
      << C4 << "b" << C5 << "fdf" << C4 << "b" << C5 << "fff"
      << C4 << "b" << C5 << "fdf" << C4 << "b" << C5 << "fdf" << C4
      << "b" << C5 << "dgd" << C4 << "b" << C5 << "fdf" << C4
      << "b" << C5 << "dgd";
   //68
   play << C4 << "b" << C5 << "fdf" << C4 << "b" << C5 << "fdf" << C4 << "b"
      << C5 << "fff" << C4 << "b" << C5 << "fdf" << C4 << "b" << C5 << "fdf"
      << C4 << "b" << C5 << "dgd" << C4 << "b" << C5 << "fdf" << C4 << "b"
      << C5 << "dgd" << HHALF << "fe" << HHOLE << "d" << "    " << HHALF
      << "de";
   //71
   play << HHOLE << C4 << "b  " << HHALF << "ba" << HHOLE << "aaaa" << "aaaa"
      << C5 << "c" << C4 << "g" << C5 << "c" << C4 << "g"
      << C5 << "c" << C4 << "g" << C5 << "c" << C4 << "g";
   //76
   play << "aeae" << "aeae" << "gdgd" << C5 << "gfed";
   //80
   play << C5 << "c" << C4 << "g" << C5 << "c" << C4 << "g"
      << C5 << "c" << C4 << "g" << C5 << "c" << C4 << "g"
      << "aeae" << "aeae";
   //84
   play << "gdgd" << "gdgd" << HHALF << C5 << "gege" << QUART << "gf"
      << HHALF << "ede";
   //87
   play << QUART << "gf" << HHALF << "edefegf" << "gege" << QUART << "gf"
      << HHALF << "ede";
   //89
   play << QUART << "gf" << HHALF << "edefegf" << "gege" << QUART << "gf"
      << HHALF << "ede";
   //91
   play << QUART << "gf" << HHALF << "edefegf" << "gege" << QUART << "gf"
      << HHALF << "ede";
   //93
   play << QUART << C5 << "gf" << HHALF << "edefegf" << C4 << "g" << C5 << "c"
      << HHOLE << " c" << C4 << "bb" << "a gfe";
   // 96
   play << "dg  " << play.C[2] << HHALF << "cbcbcbcb" << "cbcbcbcb" << C4
      << "b" << C5 << "ff" << C4 << "b" << C5 << "ff";
   //100
   play << C4 << "b" << C5 << "ff" << C4 << "b" << C5 << "ff" << C4 << "a" << C5
      << "ee" << QUART << "d" << C4 << "bged" << C3 << "b" << HHALF << "a"
      << C4 << "a" << C3 << "a" << C4 << "a" ;
   //103
   play << C3 << "a" << C4 << "a" << C3 << "a" << C4 << "a" << HHOLE << "bbbag"
      << "gggg" << "ffffe" << "dddd";
   //108
   play << C3 << HHALF << "b" << C4 << "c" << C3 << "a" << C4 << "c" << C3 << "b"
      << C4 << "c" << C3 << HHOLE << "a"
      //
      << HHALF << "b" << C4 << "c" << C3 << "bbb" << C4 << "c" << HHOLE << C3
      << "a"
      //
      << C3 << HHALF << "b" << C4 << "c" << C3 << "a" << C4 << "c" << C3 << "b"
      << C4 << "c" << C3 << HHOLE << "a";
   //111
   play << HHALF << "b" << C4 << "c" << C3 << "bbb" << C4 << "c" << HHOLE << C3
      << "a"
      //
      << C3 << HHALF << "b" << C4 << "c" << C3 << "a" << C4 << "c" << C3 << "b"
      << C4 << "c" << C3 << HHOLE << "a";
   //113
   play << HHALF << "b" << C4 << "c" << C3 << "bbb" << C4 << "c" << HHOLE << C3
      << "a"
      //
      << C3 << HHALF << "b" << C4 << "c" << C3 << "a" << C4 << "c" << C3 << "b"
      << C4 << "c" << C3 << HHOLE << "a";
   //115
   play << C5 << HHOLE << "dc" << C4 << "ba" << "bafa";
   //117
   play << C5 << HHOLE << "dc" << C4 << "ba" << "cccc" << "cccc" << "cccc";
   //121
   play << "cccc" << "cfcf" << "cfcf" << "cfcf" << "cfcf" << HHALF << "gf";
   //126
   play << HHOLE << "f" << C3 << "f" << "   " << "   " << C4 << HHALF
      << "fe" << HHOLE << "d" << "d" << "  " << C5 << "ddcc";
   //131
   play << C4 << "bb" << C3 << "b" << C4 << "b" << C3 << "bb" << C4 << "bb";
   //play << C3 << "bb" << C4 << "bb";
   play << QUART << C3 << "dfadfa" << C4 << "c" << C3 << "af" << C4 << "c" << C3 << "af";
   play << QUART << C3 << "dfadfa" << C4 << "c" << C3 << "af" << C4 << "c" << C3 << "af";
   //134
   //play << C3 << "bb" << C4 << "bb";
   play << QUART << C3 << "dfadfa" << C4 << "c" << C3 << "af" << C4 << "c" << C3 << "af";
   play << QUART << C3 << "dfadfa" << C4 << "c" << C3 << "af" << C4 << "c" << C3 << "af";
   //135
   play << QUART << C3 << "dfa" << C4 << "c" << C3 << "af" << "d" << C2 << "afd" << C1 << "af"
      << C4 << HHOLE << "c ";
}


The Project is now complete.

You can get the executable here http://rapidshare.com/files/26353466/Project1.exe.html

The project compiles in VS2005 and most likely compiles in VC++2005 Express. I don't know about others though.



Last edited by ahayes on 16 Apr 2007, 1:22 pm, edited 5 times in total.

ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

14 Apr 2007, 2:28 am

the posted play.h and play.cpp may be used under the GPL

this is windows only, unless you find another library with a Beep(frequency, duration) function on your platform



ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

14 Apr 2007, 2:43 am

http://upload2.net/page/download/4oo9AY ... l.exe.html

There is a link to the current executable. I can't gaurantee it doesn't have a virus, so you better scan it.



sunnycat
Veteran
Veteran

User avatar

Joined: 10 Feb 2007
Gender: Female
Posts: 1,061
Location: Mysterious Forest of Legends, Kitty Dream Planet

14 Apr 2007, 3:53 am

Wow...you know, honestly, I can't interpret program languages so I don't really know what's going on...but it looks like a sophisticated program... Could you explain what this program is supposed to do? Excuse me my ignorance...



ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

14 Apr 2007, 4:19 am

sunnycat wrote:
Wow...you know, honestly, I can't interpret program languages so I don't really know what's going on...but it looks like a sophisticated program... Could you explain what this program is supposed to do? Excuse me my ignorance...


It plays music.



RedMage
Veteran
Veteran

User avatar

Joined: 8 Nov 2006
Gender: Female
Posts: 6,812

14 Apr 2007, 4:22 am

Cool, even though I don't get computer language.



calandale
Veteran
Veteran

User avatar

Joined: 9 Mar 2007
Gender: Male
Posts: 12,439

14 Apr 2007, 5:32 am

If you're interested in this kind of stuff, you might want to play with some VOIP protocols.



ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

15 Apr 2007, 7:27 pm

Update: Now I have 113 measures finished!

22 more to go.



ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

15 Apr 2007, 8:21 pm

Got the last 23 measures, will post in a few hours.



ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

15 Apr 2007, 9:15 pm

Update: Project has finished!

Both the latest source and the executable are up in the original post.



lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 76
Gender: Male
Posts: 9,795
Location: Somerset UK

16 Apr 2007, 12:40 am

Interesting idea. I'd suggest that you think about better ways to encrypt the music though. The problem with the way you've done it is that it's a nightmare to see what's happening and, essentially, a new tune is a total rewrite.

I also hate numbers in programs -especially ones you can calculate trivially (the 1/16...16 note length figures).

You've not gone for an "even tempered" scale - where did the note frequency numbers come from?

I've done pretty much the same sort of thing as this, in the past, but used a plain text steam of characters to drive it all. One idea I stole from somewhere (MSDOS?) was to use both lower and upper case, so you had a two octave span going all the time.

I've just dredged up where I did do much this sort of thing. It was a hospital bedside pay TV plus telephone, etc project. I had to generate a few "alert" type noises. It was so much easier to write the code to take a plain text string, all easily readable. I think it only ever played half a dozen different sequences, but juggling them about to be suitable (tasteful?) was so easy.

You might find it interesting to look at how midi data is handled. The midi stream is quite well defined and obviously works!


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer


ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

16 Apr 2007, 2:50 am

update, a new executable is provided, the other one might not work for you, the new one is compiled with mingw instead of VS2005.

The constants come from what I've read from music sites.

http://en.wikipedia.org/wiki/Notes

That's where I got the particular frequencies, then I multiplied them by .0625, .125, .25, .5, 2.0, 4.0, 8.0, 16.0 to get C0 (it's beyond the range of the function and human hearing so it does nothing as in one NOP), C1, C2, C3, C5, C6, C7, C8. The default is C4.

I've thought about using different cases for adjacent pairs of octaves. Changing the interpreter to change octaves and timing would mean a major overhaul of the code though.

I'm now looking for ways to put FMOD in place of Beep(duration, frequency) so it runs on things other than windows using a sound card but it's rather complicated.



lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 76
Gender: Male
Posts: 9,795
Location: Somerset UK

16 Apr 2007, 11:15 am

ahayes wrote:
update, a new executable is provided, the other one might not work for you, the new one is compiled with mingw instead of VS2005.

The constants come from what I've read from music sites.

http://en.wikipedia.org/wiki/Notes

That's where I got the particular frequencies, then I multiplied them by .0625, .125, .25, .5, 2.0, 4.0, 8.0, 16.0 to get C0 (it's beyond the range of the function and human hearing so it does nothing as in one NOP), C1, C2, C3, C5, C6, C7, C8. The default is C4.
Nooo... what you have taken is the list labeled "Approx. Frequency [Hz]". Admittedly, with three digits of accuracy, nobody is likely to really hear the difference, but on the same Wikipedia page, you have Note frequency (hertz) which gives you what you really want. Sharps and flats?

ahayes wrote:
I've thought about using different cases for adjacent pairs of octaves. Changing the interpreter to change octaves and timing would mean a major overhaul of the code though.

Hee hee! My intention entirely. Get you working hard!
Actually, it wouldn't be the slightest problem if you had thought harder before/after coding. I do exactly the same - leap in and get something working... persevering when I know that something "feels wrong" about the way I've done it. Then you have to sit back and say to yourself "Is this it, or do I want to improve on it?". Sometimes it's done with, because you have no real intention of going further with the whole thing. Sometimes a bit of tinkering is all that's needed. Sometimes you just throw the lot away, and go back to the design stage.

ahayes wrote:
I'm now looking for ways to put FMOD in place of Beep(duration, frequency) so it runs on things other than windows using a sound card but it's rather complicated.

FMOD looks a bit like the sledgehammer/nut game. OpenAL looks more "free", but still looks like hard work! I've just spent some time delving around inside Linux, but it all seems an incredible uphill struggle, just to get a trivial note out. I'm sure I must be missing something simple...

... and maybe Csound is it. I'll load it in and see what it does.


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer


ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

16 Apr 2007, 11:22 am

Yeah, if I started out with using an interpreter I woudn't need so many overloaded operators.



ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

16 Apr 2007, 11:56 am

lets see:
cdefgabCDEFGAB for the scale from bottom to top of the clef, designating the capital letters for one octave above, and ; for a rest, or a rest by default if no character is specified

w = whole
h = half
q = quarter
i = eighth
s= sixteenth

for beat lengths

123456789 for C1, C2, C3, C4...

and the BPM can be defined by a constructor and reset by a member function or feeding it an integer

a = 0,1,2,3,4,5,6,7,8,9,10,11,12
and
a = c, c#/db, d, d#/eb, e, f, f#/gb, g, g#/ab, a, a#/bb, b
n = the n in C[N]

then we use the formula: freq=440*2^((-9+a)/12+n-4)

flats are designated by a preceding &, sharps by a prededing #



lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 76
Gender: Male
Posts: 9,795
Location: Somerset UK

16 Apr 2007, 1:03 pm

A couple more suggestions... now that I've got your head spinning...

Don't forget to allow for dot and double dot notation (for 1.5 and 1.75 extensions of note length).

Allow spaces, tabs and line feeds to be ignored, so you can lay out the text in any fashion that suits you.

Prefix or postfix for modifiers... mainly your choice, but postfix (at least of sharp/flat/dot(s)) will make it more readable as music, and "greedy" fetching of postfix operators is pretty straightforward (you just have to push the next note/pause/end back onto a stack...).

Don't try to make octave shifts particularly concise. Masses of music fits into a two octave range for the whole piece. You could use "\" and "/", say, to shift down/up an octave?

OTOH, note/pause length you want to make real tight. Not a lot you can do about that.

You might find it useful to put in bar markers. Not to actually use them to gebnerate the music, but to allow the program to warn you if they seem to have come in the wrong place.


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer