⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 note.cpp

📁 Nokia手机语音管理程序
💻 CPP
字号:
// Note.cpp: implementation of the Note class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "NokiaComposer.h"
#include "Note.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

IMPLEMENT_SERIAL(Note, CObject, SCHEMA_VERSION)

// +-------------------------------------------------------------
// |
// | Function        : IsSeparator
// | Description     : 
// |
// | c               : 
// | 
// +-------------------------------------------------------------
static bool IsSeparator(char c)
{
  return c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == ',';
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::Note
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
Note::Note() :
  tone_( ToneC ),
  duration_( 8 ),
  dot_( false ),
  sharp_ ( false ),
  octave_ (1)
{
    AssertValid();
}

Note::Note(Tone tone, int duration, int octave, bool dot, bool sharp) :
  tone_( tone ),
  duration_( duration ),
  dot_( dot ),
  sharp_ ( sharp ),
  octave_ ( octave )
{
    AssertValid();
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note
// | Descripci髇     : 
// |
// | other           : 
// | 
// +-------------------------------------------------------------
Note::Note(const Note& other) :
  tone_( other.tone_ ),
  duration_( other.duration_ ),
  dot_( other.dot_ ),
  sharp_ ( other.sharp_ ),
  octave_ ( other.octave_ )
{
    AssertValid();
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::~Note
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
Note::~Note()
{

}

// +-------------------------------------------------------------
// |
// | Funci髇         : >>
// | Descripci髇     : 
// |
// | ar              : 
// | &b              : 
// | 
// +-------------------------------------------------------------
static CArchive& operator >>( CArchive& ar, bool &b )
{
  int aux;

  ar >> aux;
  b = (aux != 0);

  return ar;
}

// +-------------------------------------------------------------
// |
// | Funci髇         : >>
// | Descripci髇     : 
// |
// | ar              : 
// | &n              : 
// | 
// +-------------------------------------------------------------
static CArchive& operator >>( CArchive& ar, Note::Tone &n )
{
  int aux;

  ar >> aux;
  n = (Note::Tone) aux;

  return ar;
}


// +-------------------------------------------------------------
// |
// | Funci髇         : Note::Serialize
// | Descripci髇     : 
// |
// | &ar             : 
// | 
// +-------------------------------------------------------------
void Note::Serialize(CArchive &ar)
{
  if( ar.IsStoring() )
  {
    AssertValid();
    ar << (int) dot_ ;
    ar << duration_ ;
    ar << octave_ ;
    ar << sharp_ ;
    ar << tone_ ;
  }
  else
  {
    ar >> dot_;
    ar >> duration_ ;
    ar >> octave_ ;
    ar >> sharp_ ;
    ar >> tone_ ;
    AssertValid();
  }
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::GetString
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
CString Note::GetString() const
{
  AssertValid();

  CString durationString;
  CString toneString;
  CString octaveString;

  // duraci髇 (1,2,4,8,16,32)
  durationString.Format("%d", duration_ );

  // puntillo
  if( dot_ )
    durationString += ".";

  // sostenido

  if( sharp_ )
    toneString += "#";

  // nota (c,d,e,f,g,a,b)
  switch( tone_ )
  {
  case Silence: toneString += "-";  break;
  case ToneC:   toneString += "c";  break;
  case ToneD:   toneString += "d";  break;
  case ToneE:   toneString += "e";  break;
  case ToneF:   toneString += "f";  break;
  case ToneG:   toneString += "g";  break;
  case ToneA:   toneString += "a";  break;
  case ToneB:   toneString += "b";  break;
  }

  if( tone_ != Silence )
  {
    // octava (1,2,3)
    Assert( octave_ >= 1 && octave_ <= 3, "octava invalida");
    octaveString.Format("%d", octave_ );
  }

  return durationString + toneString + octaveString;
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::ParseString
// | Descripci髇     : 
// |
// | string          : 
// | 
// +-------------------------------------------------------------
const char* Note::ParseString(const char* string)
{
  const int BUFSIZE = 100;
  char buffer[BUFSIZE];
  const char *p = string;

  // ya no hay mas notas
  if(*p == 0)
    throw ParserException("no quedan notas", string);

  // saltarse los espacios iniciales
  while( IsSeparator(*p) )
    p++;

  // parse duration_  
  char *q = buffer;
  while( isdigit( *p ) && (p - string) < BUFSIZE)
  {
    *q++ = *p++;
  }
  *q = 0;

  duration_ = atoi( buffer );
  if( duration_ ==  0)
  {
    throw ParserException("duraci髇 inv醠ida", string);
  }

  sharp_ = false;
  dot_ = false;


  // has dot?
  if( *p == '.' )
  {
    dot_ = true;
    p++;
  }

  // is sharp?
  if( *p == '#' )
  {
    sharp_ = true;
    p++;
  }

  // get tone
  switch( tolower(*p++) )
  {
  case 'c': tone_ = ToneC; break;
  case 'd': tone_ = ToneD; break;
  case 'e': tone_ = ToneE; break;
  case 'f': tone_ = ToneF; break;
  case 'g': tone_ = ToneG; break;
  case 'a': tone_ = ToneA; break;
  case 'b': tone_ = ToneB; break;
  case '-': 
  case 'p': tone_ = Silence; break;
  default:
    throw ParserException( "nota invalida", string);
  }

  // is sharp?
  if( *p == '#' )
  {
    sharp_ = true;
    p++;
  }

  // get octave
  if( tone_ != Silence )
  {
    if( ! isdigit( *p ))
      throw ParserException("octava invalida", string);
    
    octave_ = *p++ - '0';
  }

  // check if the new note is valid
  const char* pError;
  if(! IsValid(&pError) )
    throw ParserException(pError, string);

  // saltarse los espacios posteriores
  if( ! IsSeparator(*p) && *p != 0 )
    throw ParserException("no hay separaci髇 entre notas", string);

  while( IsSeparator(*p) )
    p++;

  return p;
}


// +-------------------------------------------------------------
// |
// | Function        : Note::GetMIDINote
// | Description     : 
// |
// | duration        : 
// | note            : 
// | 
// +-------------------------------------------------------------
void Note::GetMIDINote(int& duration, int& note) const
{
  AssertValid();

  duration = 1024 / duration_;
  note     = 60 + ((octave_-1) * 12);

  switch( tone_ )
  {
  case Silence: note = -1; break;
  case ToneC:   note += 0; break;
  case ToneD:   note += 2; break;
  case ToneE:   note += 4; break;
  case ToneF:   note += 5; break;
  case ToneG:   note += 7; break;
  case ToneA:   note += 9; break;
  case ToneB:   note += 11; break;
  default:
    Assert(0, "nota invalida");
  }

  if( sharp_ )
    note += 1;

  if( dot_ )
    duration += duration / 2;
}


// +-------------------------------------------------------------
// |
// | Funci髇         : Note::AssertValid
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
void Note::AssertValid() const
{
  const char* pError;
  Assert( IsValid(&pError), (char*) pError);
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::CheckValid
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
bool Note::IsValid(const char** ppError) const
{
  Assert( ppError != 0, "pError no puede ser nulo");

  *ppError = 0;

  // tone
  if( tone_ < Silence || tone_ > ToneB)
  {
    *ppError = "invalid tone";
    return false;
  }

  // duration
  if( duration_ != 1 &&
    duration_ != 2 &&
    duration_ != 4 &&
    duration_ != 8 &&
    duration_ != 16 &&
    duration_ != 32)
  {
    *ppError = "invalid duration";
    return false;
  }

  // dot
  if (dot_ && tone_ == Silence)
  {
    *ppError = "silences can not have dot";
    return false;
  }
    

  // sharp
  if( sharp_ && tone_ == Silence )
  {
    *ppError = "silences can not have sharp";
    return false;
  }
  if( sharp_ && tone_ == ToneE)
  {
    *ppError = "Tone E can not have sharp";
    return false;
  }
  if( sharp_ && tone_ == ToneB)    
  {
    *ppError = "Tone B can not have sharp";
    return false;
  }
  
  // octave
  if( octave_ < 1 || octave_ > 3 )
  {
    *ppError = "invalid octave";
    return false;
  }

  return true;
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::OctaveUp
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
void Note::OctaveUp()
{
  ++octave_;
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::OctaveDown
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
void Note::OctaveDown()
{
  --octave_;
}


// +-------------------------------------------------------------
// |
// | Funci髇         : Note::SemitoneUp
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
void Note::SemitoneUp()
{
  if( ! sharp_ )
  {
    sharp_ = true;


    if( tone_ == Silence )
    {
      sharp_ = false;
    }
    else if( tone_ == ToneE )
    {
      tone_ = ToneF;
      sharp_ = false;
    }
    else if( tone_ == ToneB )
    {
      tone_ = ToneC;
      sharp_ = false;
      ++octave_;
    }
  }
  else
  {
    sharp_ = false;
    switch(tone_)
    {
      case ToneC: tone_ = ToneD; break;
      case ToneD: tone_ = ToneE; break;
      case ToneF: tone_ = ToneG; break;
      case ToneG: tone_ = ToneA; break;
      case ToneA: tone_ = ToneB; break;
      default:
        Assert(0, "invalid tone");
    }
  }
}


// +-------------------------------------------------------------
// |
// | Funci髇         : Note::SemitoneDown
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
void Note::SemitoneDown()
{
  if( sharp_ )
  {
    sharp_ = false;
  }
  else
  {
    switch(tone_)
    {
    case Silence: break;
    case ToneC:   tone_ = ToneB;  --octave_; break;
    case ToneD:   tone_ = ToneC;  sharp_ = true; break;
    case ToneE:   tone_ = ToneD;  sharp_ = true; break;
    case ToneF:   tone_ = ToneE;  break;
    case ToneG:   tone_ = ToneF;  sharp_ = true; break;
    case ToneA:   tone_ = ToneG;  sharp_ = true; break;
    case ToneB:   tone_ = ToneA;  sharp_ = true; break;
    default:
      Assert(0, "invalid tone");
    }
  }
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::CanOctaveUp
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
bool Note::CanOctaveUp() const
{
  return octave_ != 3;
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::CanOctaveDown
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
bool Note::CanOctaveDown() const
{
  return octave_ != 1;
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::CanSemitoneUp
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
bool Note::CanSemitoneUp() const
{
  return (octave_ != 3 || tone_ != ToneB);
}

// +-------------------------------------------------------------
// |
// | Funci髇         : Note::CanSemitoneDown
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
bool Note::CanSemitoneDown() const
{
  return (octave_ != 1 || tone_ != ToneC || sharp_ );
}




// +-------------------------------------------------------------
// |
// | Funci髇         : ParserException::ParserException
// | Descripci髇     : 
// |
// | description     : 
// | 
// +-------------------------------------------------------------
ParserException::ParserException( const char* description, const char* string ) :
  description_(description)
{
    nextNote_ = string;

    // saltarse los espacios
    while( IsSeparator(*nextNote_) && *nextNote_ != 0 )
      ++nextNote_;

    // recuperar y saltarse la cadena de la nota erronea
    while( ! IsSeparator(*nextNote_) && *nextNote_ != 0 )
      noteString_ += *nextNote_++ ;

    // nextNote_ se queda apuntando a la siguiente nota 
}

// +-------------------------------------------------------------
// |
// | Funci髇         : ParserException::GetDescription
// | Descripci髇     : 
// | 
// +-------------------------------------------------------------
const CString& ParserException::GetDescription()
{
  return description_;
}

// +-------------------------------------------------------------
// |
// | Function        : ParserException::GetNoteString
// | Description     : 
// | 
// +-------------------------------------------------------------
const CString& ParserException::GetNoteString()
{
  return noteString_;
}

// +-------------------------------------------------------------
// |
// | Function        : ParserException::GetNextNote
// | Description     : 
// | 
// +-------------------------------------------------------------
const char* ParserException::GetNextNote()
{
  return nextNote_;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -