Category : Files from Magazines
Archive   : BYTE1087.ZIP
Filename : CPLUS.SRC
/* score_c.h - Definitions for classes related to the "score" program
written for the Byte C++ Review
May 1987 Mark E. Mallett
*/
#ifndef NULL
#define NULL (char *)0
#endif
/* This header file declares the following classes: */
class SCORE_ITEM;
class REST; // Derived from SCORE_ITEM
class NOTE; // Derived from SCORE_ITEM
class CHORD; // Derived from SCORE_ITEM
class SEQUENCE; // Relates to SCORE_ITEM
class SEQ_ITER; // Allows following a SEQUENCE
enum NOTEVAL { C, Csh, D, Dsh, E, F, Fsh, G, Gsh, A, Ash, B };
istream& operator>> ( istream&, NOTEVAL& );
class SCORE_ITEM // Base class for all score items
{
int duration; // How long this item persists
SCORE_ITEM* next; // Next SCORE_ITEM in the sequence
friend class SEQUENCE;
friend class SEQ_ITER;
friend istream& operator>> ( istream&, SCORE_ITEM& );
public:
SCORE_ITEM( int d = 3 ){ duration = d; }
~SCORE_ITEM(){}
int dur() { return duration; } // Retrieves duration value
virtual void play(); // Plays a score item
};
class REST : public SCORE_ITEM // Musical rest-- marks a place
{
public:
REST( int d = 3 ) : ( d ) {}
void play();
};
class NOTE : public SCORE_ITEM
{
NOTEVAL noteval; // Value of the note
friend istream& operator>> ( istream&, NOTE& );
public:
NOTE( NOTEVAL n = C, int d = 3 ) : ( d ) { noteval = n; }
~NOTE(){};
void play();
};
class CHORD: public SCORE_ITEM
{
int notemask; // Notes that make up this chord
friend istream& operator>> ( istream&, CHORD& );
public:
CHORD( int n = 0 , int d = 3 ) : ( d ) { notemask = n; }
~CHORD(){}
void play();
};
class SEQUENCE // Class allowing sequence operations.
{
SCORE_ITEM* item; // Points to item
SCORE_ITEM* last; // Points to last item
SEQUENCE& append( SCORE_ITEM *si )
{ if ( item == (SCORE_ITEM *)NULL ) item = last = si;
last->next = si; last = si; si->next = (SCORE_ITEM *)NULL;
return *this; }
friend class SEQ_ITER;
public:
SEQUENCE(){ item = last = (SCORE_ITEM *)NULL; };
SEQUENCE( SCORE_ITEM& si ) { item = last = &si; }
~SEQUENCE(){}
SEQUENCE& operator= ( SCORE_ITEM& si ) { item = last = &si; return *this; }
SEQUENCE& operator= ( SEQUENCE& s2 )
{ item = s2.item; last = s2.last; return *this; }
SEQUENCE& operator+ ( SCORE_ITEM& si ) { return append( &si ); }
SEQUENCE& operator+= ( SCORE_ITEM& si ) { return append( &si ); }
SEQUENCE& operator+= ( SCORE_ITEM* si ) { return append( si ); }
};
class SEQ_ITER // To follow a sequence with
{
SEQUENCE* seq; // Ptr to song header
SCORE_ITEM* si; // Ptr to current item
public:
SEQ_ITER( SEQUENCE& sq ){ seq = &sq; si = sq.item; }
~SEQ_ITER(){}
SCORE_ITEM* operator()(); // Retrieve next one
};
----------------------------------------------------------------------
/* score_c.c++ - Support functions for classes related to the "score" program
written for the Byte C++ Review
May 1987 Mark E. Mallett
*/
#include
#include
#include "score_c.h"
/* Table of correlations between note names and noteval mnemonics */
static struct { NOTEVAL nval; char* nname; } Nvtbl[13] = {
{ C, "C" },
{ Csh, "Csh" },
{ D, "D" },
{ Dsh, "Dsh" },
{ E, "E" },
{ F, "F" },
{ Fsh, "Fsh" },
{ G, "G" },
{ Gsh, "Gsh" },
{ A, "A" },
{ Ash, "Ash" },
{ B, "B" },
{ 0, "BAD" } };
void SCORE_ITEM :: play() // play for generic score_items
{
cout << "generic item: duration=" << dec(duration,3) << "\n";
}
void REST :: play()
{
cout << "rest: duration=" << dec(dur(),3) << "\n";
}
void NOTE :: play()
{
int i;
for( i = 0; i < 12; ++i )
if ( noteval == Nvtbl[i].nval )
break;
cout << "note: duration=" << dec(dur(),3)
<< " value: " << Nvtbl[i].nname << "\n";
}
void CHORD :: play()
{
int i;
int nval;
cout << "chord: duration=" << dec(dur(),3) << " value:";
for( nval = 0; nval < 12; ++nval )
if ( notemask & (1 << nval ) )
{
for( i = 0; i < 12; ++i )
if ( nval == Nvtbl[i].nval )
break;
cout << " " << Nvtbl[i].nname;
}
cout << "\n";
}
SCORE_ITEM* SEQ_ITER :: operator()()
{
SCORE_ITEM* tsi = si; // Copy of current ptr
if ( si != (SCORE_ITEM *)NULL ) si = si -> next;
return tsi;
}
istream& operator>> ( istream& s, NOTEVAL& n )
{
int i;
char namebuf[100];
s >> (char *)&namebuf[0]; // Input name
for( i = 0; i < 12; ++i )
if ( stricmp( namebuf, Nvtbl[i].nname ) == 0 )
break;
if ( i < 12 )
n = Nvtbl[i].nval;
else
cout << "Error: '" << namebuf << "' is not a note name\n";
return s;
}
istream& operator>> ( istream& s, SCORE_ITEM& si )
{
s >> si.duration;
return s;
}
istream& operator>> ( istream& s, NOTE& n )
{
s >> (SCORE_ITEM& ) n;
s >> n.noteval;
return s;
}
istream& operator>> ( istream& s, CHORD& c )
{
NOTEVAL nval;
char ch;
s >> (SCORE_ITEM& ) c;
c.notemask = 0; // No notes
for( ; ; ) // Input notenames until no comma
{
s >> (NOTEVAL &) nval; // Get next note
c.notemask |= (1 << nval);
s >> ch; // Look for semi
if ( ch == ';' ) // Quit when found
break;
s.putback( ch ); // Re-use the not-semi
}
return s;
}
----------------------------------------------------------------------
/* score.c++ - Test program for the "score" classes,
written for the Byte C++ Review
May 1987 Mark E. Mallett
*/
#include
#include
#include "score_c.h"
void play( SEQUENCE& );
main()
{
SEQUENCE song1;
NOTE c1(5), c2(10);
c1 = C;
c2 = G;
song1 = c1;
song1 = song1 + c2 + NOTE(Dsh, 7);
song1 += NOTE(Ash);
play( song1 );
cout << "\n\n";
SEQUENCE song2;
char c;
cout << "Enter each element of the song in the following formats\n\n";
cout << "r dd to enter a rest\n";
cout << "n dd note-name to enter a note\n";
cout << "c dd note-name... ; to enter a chord\n";
cout << "p to play the song\n";
cout << "x to finish\n";
for( ; ; ) // Loop until done
{
cout << "\n> "; // Issue prompt
cin >> c; // Get key character
if ( isupper( c ) )
c = tolower( c );
if ( c == 'x' )
break;
switch ( c ) // Process input
{
case 'r': // rest
REST* rest = new REST;
cin >> *rest;
song2 += rest;
cout << "rest entered\n";
break;
case 'n': // note
NOTE* note = new NOTE;
cin >> *note;
song2 += note;
cout << "note entered\n";
break;
case 'c': // chord
CHORD* chord = new CHORD;
cin >> *chord;
song2 += chord;
cout << "chord entered\n";
break;
case 'p': // Play
play( song2 ); // Play it
break;
default: // Invalid
cout << "'" << chr(c) << "' isn't valid.\n";
break;
}
}
}
void play( SEQUENCE &song ) // Routine to play a song
{
SEQ_ITER next_seq(song); // Get an iterator for the song
SCORE_ITEM *siptr;
while ( ( siptr = next_seq() ) != (SCORE_ITEM *)NULL )
siptr->play();
}
*** end Score ***
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/