Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Assetto armonico - main.cpp

main.cpp

Caricato da: AldoBaldo
Scarica il programma completo

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include "note.h"
  6.  
  7. /* ===> DESCRIZIONE <===========================================================
  8. ASSETTO ARMONICO, di Aldo Carpanelli, maggio 2016
  9. Data una tonica, il programma elabora la scala maggiore corrispondente e le
  10. triadi che costituiscono l'assetto armonico di base della tonalita'.
  11.  
  12. Gli accordi sono divisi in tre livelli:
  13.  
  14.     1. i "cardini" della tonalita'
  15.        (I, IV e V grado, accordi maggiori)
  16.     2. il \"lato oscuro\" della tonalita'
  17.        (II, III e VI grado, accordi minori)
  18.     3. la sensibile della scala
  19.        (l'unica triade diminuita che deriva
  20.        direttamente da una scala maggiore)
  21.  
  22. Il formato di immissione della tonica deve essere simile a questo: fa#
  23. ==============================================================================*/
  24.  
  25. // ===> STRINGHE <==============================================================
  26.  
  27. // la LUNGA stringa per la presentazione del programma!
  28. const char *kStrPresentazioneProgramma =
  29. " ==============================================================================\n\
  30.                                 SCALE E ACCORDI\n\
  31. ==============================================================================\n\
  32. \n\
  33. Data una tonica, il programma elabora la scala maggiore corrispondente e le\n\
  34. triadi che costituiscono l'assetto armonico di base della tonalita'.\n\
  35. \n\
  36. Gli accordi sono divisi in tre livelli:\n\
  37. \n\
  38.     1. i \"cardini\" della tonalita'\n\
  39.        (I, IV e V grado, accordi maggiori)\n\
  40.     2. il \"lato oscuro\" della tonalita'\n\
  41.        (II, III e VI grado, accordi minori)\n\
  42.     3. la sensibile della scala\n\
  43.        (l'unica triade diminuita che deriva\n\
  44.         direttamente da una scala maggiore)\n\
  45. \n\
  46. Il formato di immissione della tonica deve essere simile a questo: fa#\n";
  47.  
  48. const char *kStrNomiNote[7] = { "DO","RE","MI","FA","SOL","LA","SI" };
  49.  
  50.  
  51.  
  52. // ===> PROTOTIPI DI FUNZIONI <=================================================
  53.  
  54. void ChiediTonica( int *tonica, int *alterazione );
  55. void VisualizzaProspetto( SCALA *s,
  56.     NOTA *I, NOTA *II, NOTA *III, NOTA *IV, NOTA *V, NOTA *VI, NOTA *VII );
  57.  
  58.  
  59.  
  60. // ===> DEFINIZIONI DI FUNZIONI <===============================================
  61.  
  62. int main() {
  63.     char schema[7] = { 2, 2, 1, 2, 2, 2, 1 }; // lo schema della scala maggiore
  64.     NOTA I[3], II[3], III[3], IV[3], V[3], VI[3], VII[3]; // per le triadi
  65.     int tonica, alterazione; // per l'immissione della tonica della scala
  66.     SCALA s; // ovvio
  67.  
  68.     OttavaVisibile( false ); // le stringhe col nome delle note NON
  69.                              // comprenderanno il numero dell'ottava
  70.  
  71.     while( true ) { // ciclo infinito
  72.         system( "cls" ); // svuota la console
  73.  
  74.         // spiega in poche parole cosa fa il programma
  75.         printf( kStrPresentazioneProgramma );
  76.  
  77.         // chiede all'utente di immettere la tonica alla base della scala
  78.         ChiediTonica( &tonica, &alterazione );
  79.  
  80.         // l'oggetto scala calcola le proprie impostazioni in base alla
  81.         // tonica immessa, usando sempre lo schema della scala maggiore
  82.         s.Imposta( tonica, alterazione, schema );
  83.  
  84.         s.Triade( 0, I );     // l'oggetto SCALA s "compila" gli
  85.         s.Triade( 1, II );    // array di tre oggetti NOTA con
  86.         s.Triade( 2, III );   // le note che costituiscono gli
  87.         s.Triade( 3, IV );    // accordi costruiti sui gradi
  88.         s.Triade( 4, V );
  89.         s.Triade( 5, VI );
  90.         s.Triade( 6, VII );
  91.  
  92.         // compila la tabella coi risultati dell'elaborazione
  93.         VisualizzaProspetto( &s, I, II, III, IV, V, VI, VII );
  94.  
  95.         system( "pause" ); // attende, per dar tempo all'utente
  96.                            // di consultare la tabella (non e'
  97.                            // mica un computer, lui!!!)
  98.     } // "rimbalza" all'inizio del ciclo per un'eventuale nuova richiesta
  99.  
  100.     return 0; // qui non si arriva mai, ma e' richiesto
  101. }
  102.  
  103.  
  104. /*==============================================================================
  105. DESCRIZIONE
  106. Chiede e richiede l'immissione di una nota da utilizzare come tonica della scala
  107. da creare. La richiesta viene iterata fino all'ottenimento di un'immissione
  108. valida.
  109.  
  110. PARAMETRI
  111. tonica          Un puntatore a un valore intero che punta all'area di memoria
  112.                 nella quale verra' inserito il numero d'ordine della tonica
  113.                 immessa (zero based). Se il puntatore e' NULL, la funzione
  114.                 fallisce.
  115. alterazione     Un puntatore a un valore intero che punta all'area di memoria
  116.                 nella quale verra' inserito il grado di alterazione della tonica
  117.                 immesso (zero based). Se il puntatore e' NULL, la funzione
  118.                 fallisce.
  119.  
  120. FORMATO DI IMMISSIONE DELLA TONICA
  121. La tonica deve essere immessa sotto forma del nome della nota seguito dalla
  122. eventuale alterazione. Ad esempio, "re", "fa#", "sol", "lab" (senza virgolette).
  123. ==============================================================================*/
  124.  
  125. void ChiediTonica( int *tonica, int *alterazione ) {
  126.     if( tonica == NULL || alterazione == NULL ) return;
  127.  
  128.     int tTemp = 0x7FFF, aTemp = 0x7FFF; // valori non validi
  129.     const int kDimBuff = 16;
  130.     char buff[kDimBuff];
  131.     char *p;
  132.     int i, l;
  133.  
  134.     // chiede la prima volta
  135.     printf( "\n Inserisci la tonica della scala: " );
  136.  
  137.     // ripete fino a che non ottiene un immissione valida
  138.     while( tTemp == 0x7FFF || aTemp == 0x7FFF ) {
  139.         tTemp = 0x7FFF; // preimposta un valore non valido
  140.         aTemp = 0x7FFF; // preimposta un valore non valido
  141.         p = buff;               // "p" e' un alias
  142.  
  143.         // rileva l'input in buff, tramite il puntatore p
  144.         fgets( p, kDimBuff, stdin );
  145.         for( l=0; p[l]; ++l );
  146.         if( p[l-1]=='\n' ) p[--l] = '\0';
  147.         for( i=0; i<l; ++i ) p[i] = toupper(p[i]); // tutto maiuscolo!
  148.  
  149.         // scopre il numero che corrisponde al nome della nota
  150.         for( i=0; i<7; ++i )
  151.             if( strncmp(kStrNomiNote[i],p,2) == 0 )
  152.                 break;
  153.  
  154.         if( i != 7 ) { // se i==7, non ha trovato un nome di nota valido
  155.             tTemp = i;
  156.  
  157.             // cerca le alterazioni
  158.             while( *p!='B' && *p!='#' && *p!='\0' ) ++p;
  159.  
  160.             if( *p == '\0' ) {
  161.                 aTemp = 0; // in questo caso, non ci sono alterazioni
  162.             }
  163.             else {
  164.                 if( *p == '#' ) // c'e' un diesis
  165.                     for( aTemp=0; *p++ == '#'; ++aTemp );
  166.                 else if( *p == 'B' ) // c'e' un bemolle
  167.                     for( aTemp=0; *p++ == 'B'; --aTemp );
  168.             }
  169.  
  170.             // il programma non ammette che la
  171.             // tonica abbia diesis o bemolle doppi
  172.             if( aTemp < -1 || aTemp > 1 ) {
  173.                 // rinnova la rischiesta
  174.                 aTemp = 0x7FFF; // attribuisce ad aTemp un valore non valido
  175.                 printf( "\n Tonica non valida, riprova: " );
  176.             }
  177.         }
  178.         else {
  179.             // rinnova la rischiesta
  180.             printf( "\n Tonica non valida, riprova: " );
  181.         }
  182.     } // ripete il "while" fino a che non ottiene un'immissione valida
  183.  
  184.     // accetta tonica e alterazione trovate e le immette negli spazi di memoria
  185.     // puntati dai puntatori che costituiscono i parametri della funzione
  186.     *tonica      = tTemp;
  187.     *alterazione = aTemp;
  188. }
  189.  
  190.  
  191. /*==============================================================================
  192. DESCRIZIONE
  193. Stampa sullo schermo la tabella per la visualizzazione della scala e degli
  194. accordi elaborati.
  195.  
  196. PARAMETRI
  197. s           Un puntatore a un oggetto di classe SCALA che rappresenta la scala
  198.             di riferimento della tonalita' richiesta in immissione.
  199. I, II ecc.  Puntatori di riferimento ad array di tre oggetti di classe NOTA che
  200.             rappresentano le triadi sui diversi gradi della scala.
  201. ==============================================================================*/
  202.  
  203. void VisualizzaProspetto( SCALA *s,
  204.     NOTA *I, NOTA *II, NOTA *III, NOTA *IV, NOTA *V, NOTA *VI, NOTA *VII ) {
  205.     int i, j,  tonica, alterazione;
  206.  
  207.     // rileva il numero della nota corrispondente alla tonica
  208.     tonica = s->Grado(0).Nota();
  209.     // ricava l'eventuale alterazione della tonica
  210.     alterazione = s->Grado(0).Alterazione();
  211.  
  212.     system( "cls" ); // svuota la console
  213.  
  214.     // intesta la tabella
  215.     printf( "\n ASSETTO ARMONICO DELLA SCALA DI " );
  216.     printf( "%s", kStrNomiNote[tonica] );
  217.     if( alterazione == -1 )
  218.         printf( " BEMOLLE" );
  219.     else if( alterazione == 1 )
  220.         printf( " DIESIS" );
  221.     printf( " MAGGIORE\n " );
  222.  
  223.     // stampa una riga
  224.     for( i=0; i<54; ++i ) printf( "=" );
  225.  
  226.     // stampa l'intestazione delle colonne dei gradi della scala
  227.     printf( "\n |%-6s|%-6s|%-6s|%-6s|%-6s|%-6s|%-6s|%-6s",
  228.             "I", "II", "III", "IV", "V", "VI", "VII", "VIII" );
  229.  
  230.     // stampa i nomi dei gradi della scala
  231.     printf( "\n " );
  232.     for( i=0; i<8; ++i ) printf( "%-7s", "|" );
  233.     printf( "\n " );
  234.     for( i=0; i<8; ++i ) printf( "|%-6s", s->Grado(i).Str() );
  235.     printf( "\n " );
  236.     for( i=0; i<7; ++i ) printf( "%-7s", "|" );
  237.  
  238.     // stampa gli accordi di I, IV e V grado
  239.     for( i=0; i<3; ++i ) {
  240.         printf( "\n |%-6s", I[2-i].Str() );
  241.         printf( "%-7s%-7s", "|", "|" );
  242.         printf( "|%-6s", IV[2-i].Str() );
  243.         printf( "|%-6s", V[2-i].Str() );
  244.         printf( "%-7s%-7s", "|", "|" );
  245.     }
  246.  
  247.     // stampa gli accordi di II, III e VI grado
  248.     for( i=0; i<3; ++i ) {
  249.         printf( "\n        |%-6s", II[2-i].Str() );
  250.         printf( "|%-20s", III[2-i].Str() );
  251.         printf( "|%-6s", VI[2-i].Str() );
  252.         printf( "%-7s", "|" );
  253.     }
  254.  
  255.     // stampa l'accordo di VII grado (sensibile)
  256.     for( i=0; i<3; ++i ) {
  257.         printf( "\n" );
  258.         for( j=0; j<43; ++j ) printf( " " );
  259.         printf( "|%-6s", VII[2-i].Str() );
  260.     }
  261.  
  262.     printf( "\n\n " ); // doppio "a capo"
  263. }