Sei sulla pagina 1di 141

UNIVERSITÀ POLITECNICA DELLE MARCHE

FACOLTÀ DI INGEGNERIA
Corso di Laurea in Ingegneria Informatica e dell’Automazione

Tesi di Laurea

SVILUPPO IN C++ DI UNA INTERFACCIA UTENTE


PER L’ EDITING DEI PARAMETRI DI UNO
STRUMENTO MUSICALE ELETTRONICO
ROLAND TRAMITE PROTOCOLLO
DI CONNESSIONE MIDI

Candidato: Relatore:
Samuele PACIONI Prof. Ing. Aldo Franco
matr. 1005693 DRAGONI

Anno Accademico 2007/2008


RINGRAZIAMENTI

Ring raz io i l P ro f. Ald o Fr anc o Dra gon i p er il co sta nt e a iut o


pre sta to m i du ran te tut ta la s te su ra de l la t es i e tu tto i l
per sona le de l l ’ az i enda Rol and Eur ope S.p .a pe r i co ns ig li , l a
fi duc ia e p er l a g rand e re spon sab il it à c onc es sa mi ne ll a
rea l izza zi one d ei p rog et t i di scu s s i. Ri vol go un s inc er o
rin gr az ia men to a tu tt i i co ll egh i e ag li a m ic i p er l a
dis pon ibi l ità d im os tr ata e pe r i l sos te gno o ff er to ne i mo men t i
di ff ic i li . In fi ne vo rr ei fa re un r in gra zi am en to sp ec ia le a lla mi a
fa mi gl ia, se nza il sos te gno d el la qu al e non a vr ei rag gi unt o
ques to i mpo rta nt e t ra gua rdo.
SOMMARIO

1. - INTRODUZIONE ……………………………………………………….... 1
2. - INTERFACCE GRAFICHE, VISUAL STUDIO 6.0 ED MFC:…...…
…….CARATTERISTICHE SALIENTI …………………………………........ 5
2.1 – INTERFACCE GRAFICHE …………………………………………………………………….......... 5
2.2 – MICROSOFT VISUAL C++ 6.0 …………………………………………………….................. 11
2.3 – MICROSOFT FOUNDATION CLASS: MFC ………………………………………………..… 13
2.3.1 – MFC: DEFINIZIONE E SPECIFICHE ……………………………………………………………… 14

3. - PANORAMICA SUL PROTOCOLLO MIDI ………………………….. 22


3.1 – INTRODUZIONE …………………………………………………………………………..…………… 22
3.2 – L’ INTERFACCIA E LE PORTE MIDI …………………………………………………………..… 22
3.3 – CAVI DI COLLEGAMENTO MIDI …………………………………………………………..……. 23
3.4 – MESSAGGI MIDI E LORO STRUTTURAZIONE FISICA ………………………………… 24
3.5 – CANALI MIDI …………………………………………………………………………………………... 26
3.6 – STRUTTURA DEI MESSAGGI MIDI ………………………………………………………..…… 27
3.7 – CHANNEL VOICE MESSAGE ………………………………………………………………………. 28
3.8 – SYSTEM EXCLUSIVE MESSAGE ………………………………………………………………….. 29
3.9 – STRUTTURA SYSTEM EXCLUSIVE MESSAGE ………………………………..……………. 30
3.10 – GENERAL MIDI ……………………………………………………………………………….…….. 31
3.11 – SPECIFICHE GENERAL MIDI ………………………………………………………..………….. 32
3.12 – ROLAND GS GENERAL SYSTEM …………………………………………………..………….. 33

4. - SVILUPPO PROGETTO RODGERS i538 …………………………… 34


4.1 – INTRODUZIONE ………………………………………………………………………………..……... 34
4.2 – DESCRIZIONE FILES DI PROGETTO: BAROQUE.CPP E VOICEDATA.H .…….….. 35
4.3 – STANDARDIZZAZIONE MESSAGGIO MIDI ………………………………………….…...… 42
4.4 – PRESENTAZIONE DELL’ INTERFACCIA GRAFICA …………................................ 43

5. - COSTRUZIONE INTERFACCIA GRAFICA …………………………. 47


5.1 – PANORAMICA DAL RESOURCE VIEW ………………………………………………………... 47
5.2 – DIALOG PRINCIPALE : IDD_RODGERS_i385_GUI_DIALOG …………….……….…. 49
5.2.1 – DESCRIZIONE DELLA FUNZIONE: MODIFICATAB( ) …………………..……………. 52
5.2.2 – ELEMENTI COMBO BOX: RANK E VOICE PALETTE …………………..…………….. 54
5.2.3 – ELEMENTO COMBO BOX: MIDI DEVICE ……………………………………..…………. 55
5.2.4 – ELEMENTI GRAFICI …………………................................................................. 56
5.2.5 – PULSANTI EDIT_PAR_VOCE ED EDIT_PAR_NOTA ………………………..………… 58
5.3 – DIALOG EDIT PARAMETRI VOCE: IDD_DIALOG_PAR …………………………………. 59
5.3.1 – SPECIFICHE: ONINITDIALOG( ) ………………………………………………………………. 60
5.3.2 – MODIFICA DEI PARAMETRI …………………………………………………………………… 62
5.3.3 – INVIO MESSAGGIO MIDI …………………………………………………..………………….. 63
5.3.4 – ELEMENTI GRAFICI ………………………………………………………………..……………… 70
5.4 – DIALOG EDIT PARAMETRI NOTA: IDD_DIALOG_NOTA………………………….……… 71
5.4.1 – PULSANTE SEND SYSEX …………………………………………………..……………………. 74
5.4.2 – ELEMENTI GRAFICI ……………………………………………………………………………….. 75
5.5 – DIALOG SLIDER: IDD_DIALOG_SLIDER ………………………………………………….…… 78
5.5.1 –SPECIFICHE DI FUNZIONAMENTO …………………………………………..……………… 79
5.6 – DIALOG: IDD_SELEZIONE_VOCI_MULTIPLE …………………………………..…….……. 81
5.6.1 – SPECIFICHE_1: LISTA DI BOTTONI ……………………………………………..………….. 83
5.6.2 – SPECIFICHE_2: MODALITA’ DI FUNZIONAMENTO …………………………………. 86

6. - VERIFICA FUNZIONAMENTO DEL’ INTERFACCIA ……………... 91


6.1 – UTILIZZO DI UN MIDI-MONITOR ……………………………………….…………………….. 91
6.2 – 3 ESEMPI ESSENZIALI ………………………………………………………….…………………... 92

7. - SVILUPPI FUTURI E CONCLUSIONI ………………………………. 98


8. - APPENDICI -
- APPENDICE A - ……………………………………………………………………………………………….. 92
- APPENDICE B - ……………………………………………………………………………………………….. 106
- APPENDICE C_1 - ……………………………………………………………………………………………. 107
- APPENDICE C_2 - …………………………………………………………………………………………….. 111
- APPENDICE D – ……………………………………………………………………………………………….. 123

9. - BIBLIOGRAFIA …………………………………………………………. 130


10. - NOTE ……………………………………………………………………. 132
Capitolo 1
27 novembre 2008

1. - INTRODUZIONE

2.1 – INTERFACCE GRAFICHE

Il mondo delle tecnologie informatiche risulta attualmente caratterizzato da


innumerevoli metodologie e linguaggi di programmazione il cui sviluppo
evolutivo ed ottimizzazione vengono pedissequamente spronati dai vari
settori della ricerca scientifica, dalla implementazione produttiva nelle
molteplici aziende settoriali mondiali e dal progresso scientifico generale, i
quali volgono a soddisfare i fabbisogni di una realtà sociale ed ambientale,
all‟ insegna di una crescente complessità e globalizzazione; tutto ciò è atto a
favorire un miglioramento qualitativo dell‟ esistenza umana e del-
l‟ ecosistema in cui viviamo.

Gli elevati standard qualitativi raggiunti nei campi pertinenti il settore


informatico sono frutto di un boom tecnologico avviato negli anni 50‟ con la
nascita della prima generazione di calcolatori moderni (Von Neumann
realizzò il primo computer in grado di memorizzare interamente un
programma) e proseguito poi con l‟ avvento, negli anni 70‟- 80‟, dei primi
Micropocessori composti da una CPU (Central Processing Unit su circuito
integrato) raggiungenti frequenze di clock di 2 Mhz; l‟ evoluzione è
progredita esponenzialmente negli anni successivi integrandosi sempre più
nella quotidianità delle società civili maggiormente coinvolte in tale
cambiamento epocale. La larga diffusione di tali tecnologie in tutti gli strati
sociali è stata resa possibile grazie ad un paradigma di sviluppo che
permette a qualsiasi tipo di persona di interagire con apparecchiature
elettroniche come computer, dispositivi elettronici portatili (lettori Mp3,
Telefoni Cellulari, Videogames), strumentazione domestica (elettro-
domestici, domotica) e da ufficio semplicemente manipolando elementi
grafici (finestre, icone). Lo strato di un‟ applicazione software che si occupa
del dialogo con l‟ utente del sistema utilizzando un ambiente grafico è
definito come interfaccia grafica meglio conosciuta sotto il nome di
Graphical User Interface (GUI).

1
Capitolo 1
27 novembre 2008

La progettazione e lo sviluppo di un‟ idonea GUI è proprio l‟ aspetto


dominante dell‟ attività di tirocinio, oggetto di questa tesi, svolta nel
particolare ambito produttivo offerto dall‟ azienda Roland Europe S.p.a.,
sita ad Acquaviva Picena (AP), una dei leader mondiali nella produzione di
strumenti musicali elettronici, con numerose filiali dislocate in tutto il
globo, esempio delle più innovative ed interessanti soluzioni tecnologiche
del settore. Suddetto distretto industriale, avvalendosi dell‟ impiego di
personale altamente specializzato, gestisce tutte le fasi dei processi
produttivi garantendo standard qualitativi elevati e all‟ avanguardia,
offrendo una vasta gamma di strumenti elettronici che (in tale ripartizione
aziendale) risultano classificabili in 4 principali categorie:

 Tastiere elettroniche
 Fisarmoniche elettroniche
 Pianoforti digitali
 Organi liturgici

Uno strumento musicale di tale tipo produce elettronicamente dei suoni


emulando timbriche di stumenti reali (chitarra, pianoforte, violino, flauto,
batteria etc…) oppure creando nuove sonorità non esistenti in natura,
sfruttando svariate modalità di sintesi del suono (additiva, sottrattiva,
modulazione di frequenza). Gli aspetti che contraddistinguono tale famiglia
di strumenti elettronici sono trattati nell‟ “Appendice A” e risultano qui
elencati:

 Multitimbricità
 Polifonia
 Unità effetti integrata (Dsp)
 Sequencer
 Connessioni audio e midi

Ogni strumento inoltre include un‟ interfaccia utente dove appare possibile
modificare vari parametri che caratterizzano ogni singolo timbro (pitch,
frequenza, dinamica, volume, panpot, controlli midi, effetti e molto altro)

2
Capitolo 1
27 novembre 2008

editabili per mezzo di un monitor touch screen oppure di appositi tasti e


manopole posizionate sul pannello principale.
Tali elementi distintivi appaiono presenti anche nell‟ Organo Liturgico
RODGERs i538 (Figura 1.1 ) oggetto di studio nelle varie fasi dell‟ attività
progettuale di tirocinio, le cui caratteristiche estetiche e specifiche tecniche
di composizione vengono ampiamente evidenziate nell‟ “Appendice B”.

Figura 1.1 – Pannello principale dell‟ organo liturgico RODGERs Insignia


538-WD.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

L‟ immagine di Figura 1.1 illustra il pannello anteriore dell‟ organo e mette


alla luce il fatto che il display lcd al centro (blu) , dove vengono visualizzati
i vari parametri modificabili relativamente ad ogni singola voce, sia limitato
e quindi abbastanza ostico da utilizzare per le varie funzioni di editing ,
durante le quali occorre attraversare una lunga serie di sottomenù per
raggiungere la funzione desiderata. Si è ritenuto opportuno poter effettuare
tali operazioni su un Editor grafico esterno collegato tramite protocollo midi
(sistema standard di comunicazione fra strumenti musicali di cui si
evidenzieranno le caratteristiche salienti nei capitoli successivi) allo
strumento consentendone una visualizzazione ed una gestione molto più
comoda ed agevole per l‟ utente finale. Si è deciso quindi di sfruttare le
possibilità offerte dalle Microsoft Foundation Class (utilizzando il
linguaggio di programmazione ad oggetti C++) per la creazione di una
idonea Graphic User Interface avvalendosi dell‟ ambiante di sviluppo di
Visual Studio 6 su piattaforma Windows XP.
Tali scelte sono giustificabili dal fatto che il C++ è sicuramente uno dei
linguaggi maggiormente approfonditi ed appresi durante il percorso
formativo universitario; inoltre parte del progetto sviluppato fino ad ora
dall‟ azienda medesima utilizza questo stessa sintassi di programmazione ed

3
Capitolo 1
27 novembre 2008

è risultato molto più semplice collegare e migliorare le parti di software già


esistenti. Le potenzialità dell‟ applicativo Visual Studio 6 mostrano un
importante connubio tra programmazione grafica ed interoperatività a basso
livello con le svariate funzionalità del sistema operativo in cui si integra;
risulta possibile creare con estrema facilità l‟ insieme di finestre e di
elementi dell‟ interfaccia utente gestendo agevolmente anche l‟ interazione
con il sistema operativo, impiegando il modello ad oggetti delle Microsoft
Foundation Class (particolari librerie di sistema o dll). Questo insieme di
Classi C++ operano ad un livello di astrazione più elevato rispetto alle
Windows API (insieme di interfacce a basso livello in grado,tra l‟ altro, di
gestire la comunicazione con l‟hardware del calcolatore e con le periferiche
esterne) garantendo, in tale contesto applicativo, la corretta attivazione ed
utilizzazione di tutte le funzioni per l‟ interfacciamento con l‟ hardware
esterno. Le WIN32 (Windows API per piattaforme Microsoft a 32Bit) nel
tempo si sono arricchite di nuove funzionalità inglobando anche quelle
riguardanti la comunicazione con strumenti musicali elettronici nella
osservanza degli standard imposti dal protocollo MIDI.

Nei capitoli successivi verranno prima illustrate le caratteristiche generali


dell‟ evoluzione nel tempo delle interfacce grafiche, dell‟ ambiente di
sviluppo Visual Studio 6 in integrazione con le Microsoft Foundation Class
e degli aspetti fondamentali riguardanti il protocollo MIDI; successivamente
si esamineranno approfonditamente le varie fasi di ideazione e
strutturazione della comunicazione con l‟ hardware esterno (Rodgers i538) e
della creazione, gestione ed ottimizzazione dell‟ interfaccia utente
definitiva. Giungendo infine alle verifiche di corretto funzionamento dell‟
applicativo sviluppato e concludendo con l „esaminazione dellle varie
prospettive di sviluppo future valutandone gli aspetti salienti.

4
Capitolo 2
27 novembre 2008

2. - INTERFACCE GRAFICHE, VISUAL STUDIO 6.0 ED


MFC: CARATTERISTICHE SALIENTI.

2.1 – INTERFACCE GRAFICHE

GUI è l‟ acronimo di Interfaccia Grafica Utente (dall‟ inglese Graphical


User Interface), che permette all‟ utente di interagire con un computer 1
manipolando graficamente degli oggetti, senza la necessità di conoscere i
comandi da impartire tramite tastiera come invece avviene con le interfacce
testuali Command Line Interface (CLI).
Il concetto di interfaccia grafica nasce e si evolve con i primi sistemi
operativi implementati nei computer di quarta generazione, fino ad
assumere l‟ aspetto riscontrabile attualmente, concepito come un piano di
lavoro contraddistinto dallo schermo (detto scrivania o desktop), con le
icone a rappresentare i file (di cui alcune a forma di cartellina per le
directory) e le finestre ad identificare le applicazioni.
Tale ambiente di lavoro, in cui si opera attraverso il puntatore comandato
con il mouse, è stato concettualizzato dai laboratori Xerox (progetto Alto)
ed implementato per la prima volta nel 1981 nel costoso Xerox Star. La
prima versione a colori di una GUI venne introdotta da Commodore con il
suo Amiga Workbench nel 1985.

Figura 2.1a – Interfaccia Xerox Star Figura 2.1b – Interfaccia Amiga


Workbench

1
L’ interazione può avvenire con qualsiasi altro strumento elettronico che supporti tali
modalità di comunicazione.

5
Capitolo 2
27 novembre 2008

Di pari passo si sono succedute nel tempo le varie release dei più conosciuti
S.O. di casa Microsoft ed Apple rispettivamente Windows e Mac OS X fino
alle ultime versioni attualmente in commercio con l‟ introduzione di
notevoli miglioramenti grafici e prestazionali (figura 2.2).

Apple Macintosh Desktop (1984) Mircosoft Windows 1.01 (1985)

Apple Mac OS X “Leopard” (2007) Microsoft Windows VISTA (2007)

Figura 2.2 – Evoluzione nel tempo delle interfacce grafiche nei sistemi operativi
prodotti da Microsoft ed Apple.………….…………….….

In prospettiva il futuro sembra essere il Desktop 3d ed alcune soluzioni


Open Source sono già fruibili facilmente dal web (figura 2.3).

Figura 2.3 – Desktop 3d di Linux Fedora Core 6

6
Capitolo 2
27 novembre 2008

I miglioramenti che si sono verificati negli anni hanno contribuito ad una


diffusione delle interfacce grafiche in svariati campi applicativi e settoriali;
basti pensare alla fruizione dei servizi informatici nelle attività commerciali,
nelle banche, negli enti pubblici e privati, nelle telecomunicazioni e nell‟
implementazione in svariati strumenti elettronici quali cellulari, lettori MP3,
navigatori, video- games, microcomputer, elettrodomestici e strumenti
musicali.

Figura 2.4 – Esempi di interfacce grafiche dotate di touch screen


implementate.rispettivamente su un telefono cellulare ed in una tastiera
elettronica.

Nella globalità dei vari campi d‟ utilizzazione l‟ interfaccia grafica si pone


sempre tra l‟ utente ed un software applicativo dando l‟ accesso alle sue
funzionalità in modo facile ed intuitivo. L‟ interazione, quindi, è la
modalità con la quale si controlla l‟ esecuzione dell‟ applicazione tramite
tastiera, mouse, penna ottica, schermi sensibili al tatto, comandi vocali ed
altro. Essa consiste in azioni dell‟ utente che provocano reazioni (feedback)
da parte dell‟ interfaccia e possono essere classificate come:

posizionare il puntatore su un oggetto, selezionarlo, spostarlo


navigare attraverso l'interfaccia (es. menu' a cascata)
attivare una funzionalita'
trasferire informazioni (es. immettere un parametro)

Una generica interfaccia si compone di 2 elementi costitutivi:

7
Capitolo 2
27 novembre 2008

 una o piu' finestre


 vari dispositivi di interfaccia

 La finestra (in inglese window) identifica un‟ area del desktop


(schermo) attraverso cui l'utente effettua il dialogo con l'elaboratore
servendosi di una tastiera, di un puntatore tipo mouse, di una penna o di una
trackball. Essa è costituita a sua volta da:

 contorno (window frame)


 barra del titolo (title bar)
 zona di contenuto (content area)

I primi 2 sono elementi standard di tutte le window esistenti su un sistema,


definibili come "decorazioni" del window manager (WM), senza alcun
controllo da parte del programma applicativo. La barra del titolo mostra il
nome dell'applicazione che è in esecuzione nella finestra primaria nel
desktop. Nel contorno e nella barra del titolo si collocano i dispositivi di
controllo; essi rappresentano elementi visivi che l'utente puo' manipolare
con un apparato di input per compiere determinate operazioni classificabili
nel seguente modo:

 modifica della posizione (MOVE)


 modifica di altezza e larghezza (RESIZE)
 chiusura con terminazione dell'applicazione (CLOSE o QUIT)
 iconificazione (MINIMIZE)
 espansione a tutto schermo (MAXIMIZE)
 ritorno a dimensioni precedenti (RESTORE)

Nelle zona di controllo avviene l'interazione con l‟ utente (visualizzazione


di dati, raccolta di input) effettuando un collegamento diretto con
l‟applicazione a cui la finestra appartiene.

Esempi:

 editing di testi

8
Capitolo 2
27 novembre 2008

 editing di disegni
 animazione grafica tridimensionale
 menu bar (barra del menu'): contiene le funzioni principali
dell'applicazione
 area messaggi: contiene messaggi di help o di spiegazione
 status bar: mostra lo stato attuale dell'applicazione
 vari dispositivi di interfaccia

 I dispositivi di interfaccia rappresentano oggetti con aspetto grafico


e sensibilita' a particolari eventi che "popolano" una finestra ed operano la
interazione con l'utente. Si classificano in diversi tipi, ciascuno dei quali con
certe caratteristiche di aspetto e comportamento:

 Elementi attivi (sensibili a input). Esempi:

o menu' (permettono di immettere una scelta da una lista di


opzioni)
o bottoni (sensibili al click)
o dispositivi per introduzione di testo (campi di input)
o dispositivi per introduzione di valori numerici (potenziometri
lineari, circolari, digitali)

 Elementi inerti (datati di solo aspetto grafico). Esempi:

o etichette testuali
o etichette grafiche (bitmap)
o cornici ed altri elementi decorativi

 Aree dedicate a scopi speciali. Esempi:

o aree grafiche
o aree di visualizzazione ed editing di testi

9
Capitolo 2
27 novembre 2008

Figura 2.4 – Esempi di dispositivi di Interfaccia con la presenza di elementi attivi


ed inerti.

10
Capitolo 2
27 novembre 2008

2.2 – MICROSOFT VISUAL C++ 6.0

Microsoft Visual C++ 6.0 (anche noto come MSVC) è un Integrated


Development Environment (IDE2) di Microsoft per la programmazione nei
linguaggi C, C++ ed è orientato soprattutto allo sviluppo e al debug di
codice C++ basato sulle API 3 di Microsoft Windows. Risulta
particolarmente indicato per la costruzione di Graphic User Interface in
interazione con le Microsfot Foundation Class o MFC (trattate nel paragrafo
successivo). Di seguito è visionabile una schermata di esempio
caratterizzante lo ambiente di sviluppo Visual C++ mostrandone le
componenti principali.

Figura 2.5 – Interfaccia di Microsoft Visual C++. Ambiente di sviluppo


particolarmente indicato per la creazioni di applicativi Windows con elementi

2
Un integrated development environment (IDE), in italiano ambiente integrato di
sviluppo è un software che aiuta i programmatori nello sviluppo dell’ applicativo.
3
Le Application Programming Interface API (Interfa ccia di Programmazione di
un'Applicazione), sono ogni insieme di procedure disponibili al programmatore, di solito
raggruppate a formare un set di strumenti specifici per un deter minato compito. È un
metodo per ottener e un'astrazione, di solito tra l'hardware e il programmatore, o tra
software a basso ed alto livello.

11
Capitolo 2
27 novembre 2008

avanzati d „interfaccia. Risultano qui menzionati i componenti principali. Nella


workspace window sono visualizzati i file di progetto (modalità FileView).

Lo sviluppo di un‟ applicazione in ambiente Windows si basa su un progetto


(project) identificabile come un„ insieme di files di risorse relazionate la cui
compilazione e “collegamento” (linking) realizzano un programma
eseguibile (file .exe).

L „aspetto rilevante in tale ambiente di sviluppo è l‟ implementazione di un


potente editor (“compositore”) grafico per finestre di dialogo, icone,
immagini e stringhe (sono tutti elementi di interfaccia).

Figura 2.6 – Resource View di Visual C++. All‟ interno della workspace window
(“finestra di lavoro”) del visualizzatore di risorse sono esaminabili gli elementi
grafici: finestre di dialogo, icone, menù e string table.

Questo strumento permette al programmatore l‟ inserimento di controlli di


Windows e anche controlli di tipo ActiveX. Ogni progetto possiede un file
RC (resource script) di tipo testuale che descrive gli elementi d„ interfaccia
utilizzati.
Nel Visual C++ si delinea anche la presenza di un visualizzatore di classi
(strumento coadiuvante nella programmazione C++).

12
Capitolo 2
27 novembre 2008

Figura 2.7 – Class View di Visual C++. Diagramma a grafo della gerarchia delle
classi.

Compare qui una diagramma a grafo della gerarchia delle classi.


Selezionando una classe è possibile visionare le classi derivate o le classi di
base con le rispettive funzioni membro.

2.3 – MICROSOFT FOUNDATION CLASS: MFC

Lo sviluppo in ambiente Windows, come introdotto dal paragrafo


precedente, si e‟ orientato, nel corso degli ultimi anni,verso il linguaggio
C++ Object Oriented, utilizzato congiuntamente alla libreria di classi MFC.
Le applicazioni Windows operano utilizzando un modello di
programmazione chiamato “event driven”; consiste nel gestire la reazione
del programma di fronte ad eventi (ad esempio la pressione del pulsante del
mouse o la chiusura di una finestra) che vengono segnalati all‟applicazione
tramite messaggi inviati dal sistema operativo.In sostanza un‟applicazione
Windows non ha un vero e proprio main, ma si limita ad aprire una o
piu‟finestre e a posizionarsi in un ciclo di attesa (loop dei messaggi),

13
Capitolo 2
27 novembre 2008

aspettando che il sistema operativo invii messaggi all‟applicazione in


risposta ai vari eventi che si possono verificare durante l‟esecuzione del
programma. I messaggi in arrivo diretti ad una applicazione vengono
accodati in attesa dell‟elaborazione e solitamente si continua l‟esecuzione in
questo modo fino all‟arrivo di un messaggio di richiesta di terminazione del
programma (WM_QUIT), che generalmente viene inviato quando l‟utente
preme il tasto „x‟ su di una finestra, oppure seleziona la voce „Esci‟ dalla
barra dei menu. La complessita‟ di sviluppo delle applicazioni Windows
deriva pertanto dalla necessita‟ di prevedere in fase di progetto tutti i
possibili messaggi che dovranno essere gestiti e che quindi richiederanno la
scrittura di una routine di gestione apposita.……………………………..
La libreria MFC semplifica questo processo prendendosi carico di gestire al
suo interno gran parte dei messaggi che l‟applicazione riceve e lasciando
quindi al programmatore solo la scrittura della logica del programma.

2.3.1 – MFC: DEFINIZIONE E SPECIFICHE

Microsoft Foundation Classes, meglio conosciuta con l'acronimo MFC, è


una libreria di classi C++ prodotta da Microsoft con lo scopo primario di
incapsulare all‟interno di classi (piu‟ di 200 nella versione 6.0) le API di
Windows e di fornire inoltre un ambiente di programmazione Windows ad
oggetti che aiuti il programmatore nel complesso meccanismo di sviluppo
delle applicazioni dotate di interfaccia grafica. Le classi MFC forniscono
un architettura di sviluppo che semplifica la gestione dei compiti piu‟
ripetitivi di ogni applicazione Windows come la gestione dei messaggi, ed
offre inoltre alcuni potenti strumenti per separare l‟implementazione dei dati
di un programma dalla sua rappresentazione grafica raggiungendo un livello
di astrazione sensibilmente maggiore rispetto all‟SDK 4 .

4
Software Development Kit (più brevemente SDK) è un termine che in italiano si può
tradurre come "pacchetto di sviluppo per applicazioni", e sta a indicare un insieme di
strumenti per lo sviluppo e la documentazione di software.

14
Capitolo 2
27 novembre 2008

Possiamo riassumerne gli aspetti salienti in tale schema:


 Mappa dei Messaggi
 Device Context
 Intercettazione di dispositivi di input
 I controlli di base
 Dialog Box

 Mappa dei Messaggi - Il loop dei messaggi e le funzioni di


callback che venivano utilizzate con l‟SDK sono state incapsulate
all‟interno di MFC e quindi il programmatore deve solo utilizzare le macro
BEGIN_MESSAGE_MAP e END_MESSAGE_MAP per specificare quali
saranno i messaggi gestiti dalla sua applicazione. Di seguito un esempio
implementativo:

BEGIN_MESSAGE_ MAP (C MainWindow, CFrameWnd)

ON_WM_PAINT ()

END_MESSAGE_ MAP ()

E‟ possibile effettuare anche una classificazione dei principali messaggi


riguardanti una window:

Messaggio Descrizione
WM_CHAR Un carattere è inserito da tastiera
L‟ utente seleziona un elemento dal menù o un
WM_COMMAND
controllo invia una notifica alla finestra “parente”
WM_CREATE E‟ creata una finestra
WM_DESTROY E‟ chiusa una finestra
WM_LBUTTONDOWN Il tasto sinistro del mouse risulta schiaccciato
WM_LBUTTONUP Il tasto sinistro del mouse risulta rilasciato
WM_MOUSEMOVE Il puntatore del mouse risulta in movimento
WM_PAINT Un finestra deve essere ridisegnata (aggiornata)
M_QUIT L‟ applicazione viene terminata
WM_SIZE Un finestra risulta ridimensionata

 Device Context - Per poter disegnare all‟interno di una finestra e‟


necessario disporre di un oggetto denominato “Device Context” che serve
ad astrarre cio‟ che si vuole disegnare dal destinatario fisico del disegno
(schermo o stampante indipendentemente dalla risoluzione, numero dei
colori, modello della scheda video ecc.).

15
Capitolo 2
27 novembre 2008

Non e‟ possibile effettuare alcun tipo di output diretto su di una finestra


senza l‟utilizzo di un Device Context. Una volta istanziato l‟oggetto di tipo
Device context e‟ possibile richiamarne il metodo DrawText per inviare del
testo ad un area rettangolare all‟interno della finestra definita istanziando un
oggetto di classe CRect. Dal questo brano di codice si comprende che la
sequenza di passi per disegnare su di una window e‟ sempre composta da:

 Creazione di un oggetto device context


 Creazione di eventuali oggetti che modificano le caratteristiche del
disegno (come CPen e CBrush)
 Salvataggio del vecchio oggetto associato al device context
 Utilizzo delle funzioni di disegno con le nuove caratteristiche tramite
il device context
 Ripristino delle condizioni iniziali del device context
 Rilascio del device context (distruzione); implicita quando la
funzione OnPaint esce di visibilita‟.

 Inte rcettazione di dispositivi di input - Come si puo‟ gia‟ intuire


da quanto detto fino ad ora riguardo alla programmazione Windows,
l‟intercettazione dell‟input proveniente dal mouse e dalla tastiera
(dispositivi di input) avviene tramite la gestione di appositi messaggi da
parte dell‟applicazione.
Ad esempio la pressione dei tasti del mouse ed il suo movimento sono
comunicati dal sistema operativo alle applicazioni tramite una serie di
messaggi come ad esempio WM_LBUTTONDOWN, che indica che il
pulsante sinistro del mouse e‟ stato premuto, oppure WM_MOUSEMOVE
che indica che il mouse e‟ stato mosso al di sopra della finestra
dell‟applicazione.
Il programma che vuole gestire questi eventi deve aggiungere alla mappa
dei messaggi l‟indicazione dei messaggi a cui e‟ interessata e deve fornire le
corrispondenti routine di gestione per gli eventi ricevuti.
Prendendo in esame un‟ applicazione di esempio risulta possibile effettuare
la seguente analisi del file header:

16
Capitolo 2
27 novembre 2008

// l’applicazione gestisce la pressione del tasto destro


// e sinistro del mouse e il doppio click del tasto
// sinistro
afx_msg void OnLButtonDown (UINT nFlags, CPoint point);
afx_msg void OnLButtonDblClk (UINT nFlags, CPoint point);
afx_msg void OnRButtonDown (UINT nFlags, CPoint point);

Nella mappa dei messaggi si ha l‟associazione tra eventi e corrispondenti


routine di gestione:

BEGIN_MESSAGE_ MAP (C MainWindow, CWnd)



ON_WM_LBUTTONDOWN ()
ON_WM_LBUTTONDBLCLK ()
ON_WM_RBUTTONDOWN ()

END_MESSAGE_ MAP ()

e nel file.cpp si troveà l‟implementazione delle varie routine di gestione


degli eventi legati al mouse:

// in questo caso l’implementazione della routine di

// gestione per l’evento double click del pulsante sinistro

void CMainWindow::OnLButtonDblClk (UINT nFlags, CPoint point)

{

CClientDC dc (this);

if (dc.GetPi xel (point) == RGB (0, 0, 0))

ResetGame (); …

Ogni messaggio derivante da una operazione di input da parte dell‟utente su


mouse e tastiera avra‟ argomenti di input diversi che poi andranno utilizzati
nell‟implementazione della funzione di gestione; ad esempio il messaggio
LBUTTONDBLCLK invia alla funzione di gestione un oggetto di tipo
CPoint contenente le coordinate del punto in cui e‟ stato effettuato il doppio
click del mouse ed un intero contenente un flag che specifica informazioni
addizionali come lo stato dell‟altro pulsante oppure se alcuni tasti speciali
della tastiera come CONTROL e SHIFT risultavano premuti al momento
del doppio click. Le coordinate vengono gia‟ passate dal sistema operativo
in maniera relativa rispetto alla finestra dell‟applicazione e quindi possono
essere facilmente utilizzate dal programmatore.

17
Capitolo 2
27 novembre 2008

 I controlli di base – I controlli possono essere considerati come i


“mattoni” che servono a costruire l‟interfaccia di qualsiasi applicazione
Windows.

In generale un controllo e‟ uno speciale tipo di finestra che permette di


interagire con l‟utente finale, sia in termini di input che di output; i piu‟
comuni controlli utilizzati in pressoche‟ tutte le applicazioni Windows sono
bottoni, label, textbox, listbox, combo box e check box.
Naturalmente esistono molti altri controlli, ed altri se ne aggiungono via via
che l‟interfaccia delle varie versioni di Windows viene migliorata ed
evoluta; il programmatore li puo‟ utilizzare come oggetti preconfezionati
(classi in MFC) tramite la loro interfaccia senza preoccuparsi di come siano
stati implementati. Per utilizzare i controlli di Windows all‟interno delle
applicazioni MFC in genere si procede in questo modo:

 Nel .h della classe che implementa la finestra si aggiungono gli


oggetti che si vorranno visualizzare nella finestra sotto forma di
oggetti membro di tipo variabile a seconda della classe di oggetto
(es. CButton m_myButton, CListbox m_myListBox ecc.)

 Al momento della creazione della una finestra si creano anche i


controlli che sono contenuti nella finestra (chiamando i metodi
create delle varie classi MFC che implementano i controlli come
CButton, CListbox ecc.).

 Nella mappa dei messaggi vanno aggiunti gli eventi generati dai
controlli utilizzati; ad esempio il controllo bottone genera un evento
ON_BN_CLICKED che viene generato al momento della pressione.

 Gli eventi dei controlli che si desidera gestire vanno associati alle
corrispondenti routine di gestione (es. OnButtonClicked).

 Le routine di gestione vanno implementate all‟interno


dell‟applicazione.

Ogni controllo ha le sue caratteristiche, attributi ed eventi che puo‟ generare


con relativi differenti prototipi delle routine di gestione; e‟ chiaro quindi che

18
Capitolo 2
27 novembre 2008

e‟ necessario leggere la documentazione di ogni tipo di controllo per poterlo


utilizzare correttamente all‟interno delle proprie applicazioni.

 Dialog Box - Nelle applicazioni Windows di solito i controlli non


vengono posizionati nella finestra principale dell‟applicazione, ma in
speciali finestre progettate per la raccolta dell‟input da parte dell‟utente
dette “dialog box”.

Un esempio puo‟ essere la finestra di salvataggio dei file che troviamo in


tutte le applicazioni Windows oppure la finestra in cui si definiscono le
opzioni di stampa.

Per inserire una dialog box in una applicazione MFC e‟ necessario ereditare
una propria classe dalla classe base CDialog, inserire i controlli all‟interno
della dialog, ed eventualmente implementare alcune funzioni virtuali che
gestiscono il comportamento della dialog. In sintesi i passi da seguire per
aggiungere ad una applicazione una semplice dialog box che richiede l‟input
di un campo test e di uno numerico (listato 2_2_4), sono questi:

 Sebbene sia possibile fare tutto manualmente e‟ bene in questo caso


avvalersi dell‟aiuto dell‟ambiente di sviluppo per la creazione della
struttura base della dialog e quindi dal menu Insert selezionare New
Form, scegliere come classe base CDialog e specificare il nome; il
Visual Studio provvedera‟ a creare il file di risorse, ed i file .cpp e .h
per la nostra nuova dialog.

 A questo punto risulta possibile aprire il resource editor e


modificare l‟aspetto della dialog box aggiungendo i controlli di
input necessari (i bottoni OK e CANCEL con la relativa gestione
base sono gia‟ stati implementati dallo Wizard).

 Una volta aggiunti i controlli di input graficamente e assegnato loro


un nome (es. IDC_EDITNAME) e‟ necessario aggiungere nel .h
tante variabili membro della classe CMyDialog quanti sono i campi
associati ai controlli di input.

19
Capitolo 2
27 novembre 2008

 E‟ necessario poi effettuare l‟associazione tra le variabili membro


ed i controlli di input e definire se devono essere effettuati controlli
di validazione sull‟input inserito
 Una volta preparata la dialog box e‟ possibile richiamarla
dall‟applicazione istanziando un oggetto di tipo CMyDialog in
maniera “modale” (la dialog non si chiude fino a che non si preme
Ok o Cancel e non si puo‟ passare ad altre finestre) oppure “non
modale” la dialog puo‟ esssere chiusa e trattata come le finestre
tradizionali.

Viene proposta una finestra di dialogo di default, che risulta


personalizzabile con i controlli (già in parte illustrati), che possono
contenere:

 immagini
 testo statico
 testo editabile
 raggruppamenti
 pulsanti
 Check box
 radio box
 combo box
 list box
 scroll bar orizzontali
 scroll bar verticali
 spin
 progress
 slider
 hot key
 list control
 tree control
 tab control
 animazioni

20
Capitolo 2
27 novembre 2008

 rich edit
 custom control

Figura 2.8 – Finestra di dialogo di default, che si può personalizzare con l‟


inserimento grafico deii controlli prelevabili dalla barra verticale a destra e
precedentemente elencati.

Dal ClssWizard relativo ad una Dialog risulta possibile l „intera gestione


delle variabili membro e delle funzioni membro associate ad essa.

Figura 2.9 – Con il ClssWizard relativo ad una Dialog risulta possibile l „intera
gestione delle variabili membro e delle funzioni membro associate ad essa .

21
Capitolo 3
27 novembre 2008

3. - PANORAMICA SUL PROTOCOLLO MIDI

3.1 – INTRODUZIONE

MIDI è l'acronimo di Musical Instrument Digital Interface, ovvero una


interfaccia digitale per strumenti musicali. Più precisamente il midi è un
protocollo di comunicazione in quanto standard riconosciuto nel mondo da
tutti i costruttori, non solo di strumenti musicali, ma anche
d‟apparecchiature informatiche e audio/video. Il protocollo MIDI quindi
stabilisce le specifiche sia hardware ( interfaccia, cavi, connettori ), sia
software ( linguaggio informatico, modalità di trasmissione, tipologia dei
messaggi ) che ogni apparecchiatura deve “saper comprendere ” se desidera
essere veramente MIDI compatibile. Perciò è stato necessario costruire una
interfaccia di comunicazione e creare un linguaggio di comunicazione.
I messaggi che gli strumenti si possono scambiare sono svariati: suona il
DO della terza ottava, abbassa il volume al pianoforte (manda sul canale
audio destro il suono del violino ecc.). Questi messaggi viaggiano
attraverso un cavo che collega gli strumenti e risultano caratterizzati da
valori discreti compresi tra 0 e +5 volt; e si distinguono dai messaggi audio
(che sono variazioni continue di tensione). Rappresentano quindi segnali
digitali cioè sequenze di 0 ed 1.

3.2 – L’ INTERFACCIA E LE PORTE MIDI

L'interfaccia midi è il dispositivo (costruito secondo regole ben precise) che


consente alle apparecchiature di dialogare tra loro ed utilizza delle porte
d'ingresso e di uscita per ricevere e trasmettere i dati. Queste porte si
chiamano rispettivamente MIDI-IN e MIDI-OUT. L'interfaccia garantisce il
funzionamento della trasmissione. La trasmissione dei dati avviene alla
velocità di 31250 bit al secondo, ovvero 1 bit ogni 32 milionesimi di
secondo e risulta definita come asincrona, ovvero occorre un bit di start e

22
Capitolo 3
27 novembre 2008

uno di stop oltre agli otto bit della trasmissione. Quindi un byte che viene
ricevuto o trasmesso dall' interfaccia midi è composto da 10 bit .

Le porte, come già è stato detto, si dividono in:

 MIDI-IN: è la porta che riceve i dati trasmessi da una


apparecchiatura musicale.

 MIDI-OUT: è la porta che serve a trasmettere i dati ad altre


apparecchiture musicali.

 MIDI-THRU: è una porta che bypassa il segnale ricevuto alla


porta MIDI-IN.

Il segnale così, inalterato, può essere trasmesso ad un'altra apparecchiatura


musicale.

E' importante quando si esegue il collegamento di apparecchiature musicali


ricordare che:

 La porta MIDI-IN va collegata ad una porta MIDI-OUT o


MIDI-THRU.

 La porta MIDI-OUT deve essere collegata esclusivamente ad


una porta MIDI-IN.

 La porta MIDI-THRU deve essere collegata esclusivamente ad


una porta MIDI-IN.

3.3 – CAVI DI COLLEGAMENTO MIDI

I cavi utilizzati per la trasmissione di dati midi sono composti da cinque fili,
anche se in realtà ne vengono utilizzati solo tre. Il connettore per il
collegamento alle porte MIDI-IN,OUT, THRU è a cinque poli. Due poli e
due cavi non vengono praticamente utilizzati.

23
Capitolo 3
27 novembre 2008

Figura 3.1 – Connettore standard MIDI di tipo DIN a 5 pin

Il connettore standard MIDI (Figura 3.1 ) è di tipo DIN (Deutshe Industre


Normen) a 5 pin:

 Il pin 1 e 3 sono riservati per sviluppi futuri (non utilizzati).


 Il pin 2 è collegato a massa (per evitare interferenze).
 Il pin 5 collega il filo necessario per la trasmissione dei dati, mentre
il pin 4 collega il cavo che assicura l'alimentazione corretta a + 5V.

Importante risulta anche il tipo di collegamento USB to MIDI con cui è


possibile connettere un‟ applicazione su PC, che sfrutta il protocollo midi,
con uno o più device (dispositivi) esterni.

Figura 3.2 – Cavo di collegamento “USB to Midi” (per interfacciamento di un PC


con un hardware esterno midi)

3.4 – MESSAGGI MIDI E LORO STRUTTURAZIONE FISICA

Con l'interfaccia MIDI è possibile collegare insieme tastiere, expanders


(moduli contenenti suoni), computer,pedaliere MIDI, e tutto ciò che abbia
un'interfaccia MIDI. L'insieme di tutti i messaggi che le macchine si
possono scambiare costituiscono il protocollo MIDI.

24
Capitolo 3
27 novembre 2008

Dunque è un sistema di comunicazione dati, che consente ad uno strumento


musicale o altro dispositivo (detto master) di controllarne un altro (detto
slave), e anche più di uno, in modo da suonare insieme le stesse note,
cambiare i timbri nello stesso momento, iniziare (da capo o dal segno) i
brani memorizzati, mantenere la sincronizzazione. In alcuni casi , è anche
possibile, controllare altri parametri, come modulation wheel, pitch bender,
e anche i valori di inviluppo, filtri e volume.
Il protocollo MIDI dunque stabilisce le modalità con le quali devono essere
inviati i messaggi tra le varie porte MIDI di un dispositivo.
Un messaggio MIDI è composto da un insieme di byte.
Questi possono essere status byte e data byte.

BYTE

STATUS BYTE DATA BYTE

Un messaggio MIDI deve sempre iniziare con uno status byte.


 Gli status byte servono per definire in modo univoco un comando. Il bit
più significativo dello status byte è uguale ad 1 e quindi puòassumere un
valore compreso tra 128 e 255.Gli status byte trasmettono quindi il tipo di
informazione (suona una nota, alza il volume, ecc).
 I data byte invece servono per inviare gli eventuali parametri necessari
per uncorretto funzionamento dello status byte. Il bit più significativo
(MSB) del data byte è uguale a 0 e quindi un data byte può assumere un
valore decimale compreso tra 0 e 127.
Struttura di un singolo messaggio midi:

STATUS DATA DATA


BYTE BYTE 1 B YTE 2

25
Capitolo 3
27 novembre 2008

3.5 – CANALI MIDI

Le informazioni per la comunicazione fra strumenti passano attraverso il


cavo di trasmissione sfruttando un certo numero di Canali MIDI
Infatti, utilizzare un cavo MIDI per trasmettere un solo messaggio non
sarebbe conveniente e per questo motivo una linea MIDI è stata divisa in 16
canali (logici) di comunicazione. Ognuno di essi può trasmettere una
determinata informazione che può essre ricevuta da un dispositivo
sintonizzato su quel canale

Figura 3.3 – Canali MIDI. Conversione in binario ed esadecimale dei 16 canali.

26
Capitolo 3
27 novembre 2008

3.6 – STRUTTURA DEI MESSAGGI MIDI

Figura 3.4 – Strutturazione dei Messaggi Midi: Channel Message e System


Message.

I messaggi MIDI si dividono in due categorie principali:


 Channel Message
 System Message

 Channel Message - Un messaggio di canale utilizza 4 bits nello


Status Byte per l‟ indirizzamento del messaggio verso uno dei 16
canali Midi e 4 bits per definire il messaggio stesso.
Quindi i messsaggi di canale sono quelli che possono essere indirizzati ad
uno qualsiasi dei sedici canali MIDI, essi si dividono in:
Channel voice message
Channel mode message

27
Capitolo 3
27 novembre 2008

 System Message - Questi messaggi, a differenza dei Channel


message non contengono informazioni di canale,bensì di sistema,
quindi possono essere ricevuti da qualsiasi apparecchiatura MIDI.
Essi si dividono ulteriormente in:
System common message
System Real time message
System exclusive message

3.7 – CHANNEL VOICE MESSAGE

Analizziamo ora il particolare messaggio : Note on - Note off


Quando in uno strumento musicale elettronico si preme un tasto, esso
manda via MIDI un messaggio definito come Note on con le specifiche di
che nota si tratta, con quale intensità si stà suonando (velocity = dinamica) e
in quale ottava.
Un esempio di messaggio di Note on è il seguente:

 Status Byte: 1001cccc (Note on), cccc indica il canale di


trasmissione.
 Data Byte 1: 0nnnnnnn (Key number) gli n indicano il numero della
nota che deve essere suonata.
 Data Byte 2: 0vvvvvvv (Velocity number), le v indicano la velocità
con cui si preme il tasto.

Le note sono rappresentate da numeri: 0 per la nota C, 2 per C#, 3 per D


ecc.
Quando il tasto viene rilasciato lo strumento produce un messaggio di Note
off indicante quale tasto è stato rilasciato.

28
Capitolo 3
27 novembre 2008

3.8 – SYSTEM EXCLUSIVE MESSAGE

I messaggi di sistema esclusivo non sono assegnati ad alcun canale Midi in


particolare ed in base allo strumento specifico a cui devono essere
indirizzati assumono un propria formattazione speciale relativamente al
produttore. Infatti si è pensato di introdurre all‟interno di un messaggio di
sistema esclusivo un ID numbe r che identifichi la marca produttrice dello
strumento stesso.
Di seguito una tabella esplicativa dei principali ID number delle principali
marche:
Roland 0x41
Korg 0x42
Yamaha 0x43
Casio 0x44
Akai 0x45
Waldorf 0x3E

Tale codice identificativo indica alle apparecchiature aventi lo stesso ID


che il messaggio di sistema esclusivo è per loro e tutte le altre
apparecchiature collegate, ma con ID differente, ignoreranno quel
messaggio. Tramite i messaggi esclusivi si possono inviare dati tipo:

 parametri relativi alle patch dello strumento (esempio la curva di


inviluppo relativa di un timbro dello strumento)
 bulk dump (scaricare su un sequencer tutti i parametri che sul
nostro strumento stanno costruendo il suono)

Quindi programmando dati di sistema esclusivo si ha un controllo completo


sul comportamento dello strumento, spesso riuscendo ad accedere a funzioni
non raggiungibili in altri modi. Tipico esempio è la costruzione di un Editor
Grafico su PC che permetta di controllare i parametri e l‟ editing di uno
specifico strumento con l‟ invio di appropriati messaggi esclusivi via midi.

29
Capitolo 3
27 novembre 2008

3.9 – STRUTTURA SYSTEM EXCLUSIVE MESSAGE

 System exclusive
 Status Byte: 11110000 (Sistema esclusivo) F0H
Lo status bytes è seguito da una serie di byte che costituiscono
l‟informazione (compreso l‟ID).

 End of exclusive
 Status Byte: 11110111 (Fine messaggio) F7H
Indica la fine di messaggio di sistema esclusivo.

In particolar modo l‟ implementazione Midi realitiva al costruttore


ROLAND utilizza la seguente formattazione per tutti i messaggi esclusivi:

BYTE Description

F0H Exclusive status

41H Manufactures ID (Roland)

DEV Device ID

MDL Model ID

11H Command ID

[BODY] MainData

Sum Check sum

F7H End of exclusive

Figura 3.6 – Strutturazione dei Messaggi Midi: Channel Message e System


Message.

MIDI status: F0H, F7H


.Un messaggio esclusivo deve essere compreso tra 2
……………… status bytes, partendo con il Manufactures- ID
……………… immediatamente dopo F0H.

30
Capitolo 3
27 novembre 2008

Manufactures- ID: 41H


Manufactures- ID relativo alla Roland.

Device-ID: DEV
Il device- ID contiene un unico valore che identifica il
…………… singolo device
Relativamente alla connessione midi di più strumenti .

Model- ID: MDL


Contiene un valore che unicamente identifica un
:::::::::::::::::::: modello da un altro.

Command- ID: CMD


Indica la funzione di un messaggio esclusivo.

Main Data: BODY


Questo campo contiene i dati che si vogliono inviare
……………… con il messaggio Esclusivo.

Check Sum: sum


Somma di controllo del messaggio.

3.10 – GENERAL MIDI

Quando si cambia un timbro di uno strumento tramite il program change


(tipo di messaggio di canale) esso dà l'informazione ad un modulo sonoro
che a seconda dell'implementazione può far corrispondere il suono
desiderato oppure un altro suono completamente diverso da quello scelto.
Ad esempio, se su di un sintetizzatore A la patch 1 corrisponde ad un organo
non è detto che la patch 1 di un sintetizzatore B sia uguale, anzi potrebbe
corrispondere tutt'altro strumento.

31
Capitolo 3
27 novembre 2008

Si tratta quindi di stabilire uno standard in modo che tutti i sintetizzatori,


sebbene con suoni diversi, facciano corrispondere gli strumenti con patch
già prestabilite. Nel 1991 fu introdotto lo standard GM, general MIDI level
1.

3.11 – SPECIFICHE GENERAL MIDI

Sound Generating System


PCM wave generator + TVF (filtro) + TVA(ampiezza) + Reverb
& Chorus

Il minimo numero di polifonia deve essere 24 (o superiore)

Una risorsa sonore (modulo sonoro) deve includere 16 parti


strumentali.

Ogni parte deve corrispondere ad un canale midi individualmente.

Uno strumento musicale per essere GM compatibile deve associare


ad ogni valore di program change una patch stabilita.

Il numero dei timbri GM deve essere 128, suddivisi in 16 famiglie


con 8 strumenti ognuna.

La batteria e le percussioni devono risiedere obbligatoriamente nel


canale midi 10.

Di seguito la mappa degli strumenti GM con la patch corrispondente.

32
Capitolo 3
27 novembre 2008

3.12 – ROLAND GS GENERAL SYSTEM

Lo standard GS è un evoluzione dello standard general MIDI level 1 ed è


stato introdotto dalla Roland. Questo standard permette infatti di utilizzare
più strumenti rispetto ai 128 consentiti dal GM,e introduce nuovi tipi di
messaggi e di controller. Il GS introduce il concetto di BankSelect, esso
unito al program change permette di avere 128 variazioni per ogni singolo
strumento.
Da sottolineare il fatto che il numero di banchi a disposizione in un
sintetizzatore dipende esclusivamente dal produttore dello strumento e non
dalle specifiche GS. Inoltre lo standard GS permette di modificare effetti
audio come il chorus e il reverbero ecc.

33
Capitolo 4
27 novembre 2008

4. - SVILUPPO PROGETTO RODGERS i538

4.1 – INTRODUZIONE

Lo svolgimento progettuale di ideazione e costruzione di un editor grafico di


interfacciamento con l‟ organo liturgico Rodgers i538 e di interazione con
l‟ utente finale ha attraversato diverse fasi di elaborazione e studio
riassumibili nel seguente modo:

analisi delle parti di software già sviluppate ed implementate dall‟


azienda nello strumento elettronico
individuazione ed estrapolazione dei files (C++) da utilizzare nella
modellazione dell‟ interfaccia
standardizzazione del messaggio Midi per la corretta
comunicazione con il Rodgers i538
ideazione,organizzazione ed ottimizzazione della Graphic User
Interface su più livelli di finestre (dialog)
implementazione software dell‟ interfaccia tramite MFC nell‟
ambiente di sviluppo Visual C++
verifica finale dei risultati ottenuti mediante l‟ utilizzo di un
Midi-Monitor

In collaborazione con gli ingegneri e progettisti che hanno sviluppato lo


strumento elettronico in questione, si è potuto analizzare il sofware già
implementato focalizzando le caratteristiche salienti e le modalità di
funzionamento basilari; sono stati individuati i seguenti 2 files di progetto su
cui porre le basi di collegamento e integrazione con l‟ interfaccia utente da
costruire : baroque.cpp e voicedata.h . In essi è inclusa tutta la complessa
strutturazione su più livelli delle voci caratterizzanti il Rodgers i538
evidenziandone anche il numero ed il tipo di parametri editabili al loro
interno. Nei paragrafi successivi si opererà un approfondimento su tali parti
di software e si porranno le basi per l „ideazione dell‟ interfaccia con la

34
Capitolo 4
27 novembre 2008

prerogativa di rispettare gli standard imposti sia dal protocollo midi sia dai
modelli grafici di costruzione trattati nei capitoli introduttivi.

4.2 – DESCRIZIONE FILES DI PROGETTO: BAROQUE.CPP E


………VOICEDATA.H

Il pannello principale dell‟ organo liturgico Rodgers i538 (Figura 1.1) e


l‟ “Appendice B” che ne descrive le caratteristiche tecniche, mettono in
risalto la sua strutturazione fisica di base; le parti dello strumento suonabili
da un musicista sono 3:
1. Pedaliera
2. Tastiera inferiore
3. Tastiera superiore
Ad ognuna di esse l‟ esecutore può assegnare una o più voci selezionando i
tasti relativi ad ogni parte sul pannello principale. In esso è possibile
individuare (da sinistra a destra) le 3 sezioni corrispondenti alle rispettive
voci assegnabili dall‟ utente:
1. Pedal
2. Manual II
3. Manual I
Ogni voce principale è costituita da 2 livelli di sottovoci che simulano
altrettanti livelli di canne dell‟ organo. Ognuno di tali sottosezioni è
composta a sua volta da altre 8 sottovoci

Figura 4.1 – Livelli di strutturazione delle voci interne al Rodgers i538

Tutte le voci possiedono una stessa struttura di base descritta da un certo


numero di parametri direttamente editabili dall‟ utente.

35
Capitolo 4
27 novembre 2008

L‟ intera complessa architettura multilivello definita e residente


nell‟ organo liturgico appare implementata nel file baroque.cpp . E‟
evidente quindi la sua importanza basilare nello sviluppo del progetto e
nella modellazione grafica dell‟ interfaccia. Il codice sorgente completo è
visionabile nel workspace dell‟ ambiente di sviluppo Visual C++ (sono più
di mille pagine di codice e sarebbe stato impossibile allegarlo interamente in
tale progetto di tesi); è possibile estrapolarne l‟ elemento costitutivo
fondamentale:

baroque_ROM[NUMBER_OF_TIMBRES][COUPLED_VOICES][NUMBER_OF_VOICES]

Si tratta di una matrice multidimensionale composta da strutture costanti di


tipo “TRIP” le cui parti fondamentali sono individuate in un estratto, dal
suo codice completo, visionabile di seguito:

const TRIP
baroque_ROM[NUMBER_OF_TIMBRES][COUPLED_VOICES][NUMBER_OF_VOICES] = {
{
{
{
//PEDAL >> Timbri_RAM[Tab0][Rank0][VoicePalette0]
/*unsigned char Sysexcode;*/ 155,
/*unsigned char NomeVoce[LENGTH_OF_NAMES+1];*/
/*PrincipalBass16'",
/*unsigned char orgPar t_exist;*/ 0,
/*unsigned char cc32;*/ 4,
/*unsigned char cc0;*/ 0,
/*unsigned char pc;*/ 0,
/*unsigned char volume;*/ 115,
/*unsigned char filter;*/ 89,
/*unsigned char micro_panpot;*/ 3,
/*unsigned char Panpot;*/ 64,
/*unsigned char voiceFamily;*/ 8,
/*char PoliphonicPriority;*/ 1,
/*unsigned char Env_Attack;*/ 64,
/*unsigned char Env_Decay;*/ 64,
/*unsigned char Env_Release;*/ 64,
/*unsigned char Env_Delay;*/ 40,
/*unsigned char RndTune_Probability;*/ 4,
/*unsigned char RndTune_MaxCents;*/ 4,
/*unsigned char pitch;*/ 59,
/*unsigned char pipe;*/ 0,
/*unsigned char outch;*/ 1,
/*unsigned char Dummy2[7];*/ {0,0,0,0,0,0,0},
/*unsigned char ShortNomeVoce[9];*/ "Princ 16",
/*unsigned char volume_nbn[128];*/
{
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,

36
Capitolo 4
27 novembre 2008

64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64
},
/*unsigned char tone_nbn[128];*/
{
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
},
/*unsigned char pitch_nbn[128];*/
{
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64
}
},
{
//PEDAL >> Timbri_RAM[Tab0][Rank0][ VoicePalette1]
/*unsigned char Sysexcode;*/ 152,
/*unsigned char NomeVoce[LENGTH_OF_NAMES+1];*/
……………………………………………………………………………."Violon Bass 16' ",
/*unsigned char orgPar t_exist;*/ 0,
/*unsigned char cc32;*/ 4,
/*unsigned char cc0;*/ 0,
/*unsigned char pc;*/ 2,
/*unsigned char volume;*/ 113,
/*unsigned char filter;*/ 64,
/*unsigned char micro_panpot;*/ 3,
/*unsigned char Panpot;*/ 64,
/*unsigned char voiceFamily;*/ 8,
/*char PoliphonicPriority;*/ 1,
/*unsigned char Env_Attack;*/ 64,
/*unsigned char Env_Decay;*/ 64,
/*unsigned char Env_Release;*/ 64,
/*unsigned char Env_Delay;*/ 40,
/*unsigned char RndTune_Probability;*/ 4,
/*unsigned char RndTune_MaxCents;*/ 4,
/*unsigned char pitch;*/ 64,
/*unsigned char pipe;*/ 0,
/*unsigned char outch;*/ 1,
/*unsigned char Dummy2[7];*/ {0,0,0,0,0,0,0},
/*unsigned char ShortNomeVoce[9];*/ "Viol 16",
/*unsigned char volume_nbn[128];*/

37
Capitolo 4
27 novembre 2008

{
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64
},
/*unsigned char tone_nbn[128];*/
{
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
},
/*unsigned char pitch_nbn[128];*/
{
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64
}
},
{
//PEDAL >> Timbri_RAM[Tab0][Rank0][VoicePalette2]

/*unsigned char NomeVoce[LENGTH_OF_NAMES+1];*/
"Vuoto ",
….
},
{
//PEDAL >> Timbri_RAM[Tab0][Rank0][VoicePalette3]


},
{
//PEDAL >> Timbri_RAM[Tab0][Rank0][VoicePalette4]


},
{
//PEDAL >> Timbri_RAM[Tab0][Rank0][VoicePalette5]


},
{
//PEDAL >> Timbri_RAM[Tab0][Rank0][VoicePalette6]

38
Capitolo 4
27 novembre 2008


},
{
//PEDAL >> Timbri_RAM[Tab0][Rank0][VoicePalette7]


},
{
{

},
{
//PEDAL >> Timbri_RAM[Tab0][Rank1][VoicePalette1]
….

},
{
//PEDAL >> Timbri_RAM[Tab0][Rank1][VoicePalette2]

},
{
//PEDAL >> Timbri_RAM[Tab0][Rank1][VoicePalette3]

}
},
{
//PEDAL >> Timbri_RAM[Tab0][Rank1][VoicePalette4]

},
{
//PEDAL >> Timbri_RAM[Tab0][Rank1][VoicePalette5]

},
{
//PEDAL >> Timbri_RAM[Tab0][Rank1][VoicePalette6]

},
{
//PEDAL >> Timbri_RAM[Tab0][Rank1][VoicePalette7]

}
}
},
{
{
{
//PEDAL >> Timbri_RAM[Tab1][Rank0][VoicePalette0]

},
{
//PEDAL >> Timbri_RAM[Tab1][Rank0][VoicePalette1]

},
{
//PEDAL >> Timbri_RAM[Tab1][Rank0][VoicePalette2]

},
{

39
Capitolo 4
27 novembre 2008

//PEDAL >> Timbri_RAM[Tab1][Rank0][VoicePalette3]



},
{
//PEDAL >> Timbri_RAM[Tab1][Rank0][VoicePalette4]

},
{
//PEDAL >> Timbri_RAM[Tab1][Rank0][VoicePalette5]

},
{
//PEDAL >> Timbri_RAM[Tab1][Rank0][VoicePalette6]

},
{
//PEDAL >> Timbri_RAM[Tab1][Rank0][VoicePalette7]

}
},
{
{
//PEDAL >> Timbri_RAM[Tab1][Rank1][VoicePalette0]

},
{
//PEDAL >> Timbri_RAM[Tab1][Rank1][VoicePalette1]
….
},
{



}
}
}

Come si può facilmente evincere dal codice precedente, l‟ accesso alle voci
risulta possibile mediante 3 indici fondamentali:

NUMBER_OF_TIMBRES: identifica la voce di registro principale.


COUPLED_VOICES: identifica il rank (livello di canne simulate).
Vale 0 o 1.
NUMBER_OF_VOICES: identifica la “sottovoce” (da 0 a 7) del
timbro principale.

L‟ organizzazione delle voci verifica quanto già anticipato in precedenza e


messo in risalto dall‟ evidenziazione degli indici presenti nella successione

40
Capitolo 4
27 novembre 2008

delle voci. Ogni Tabx è datato di 2 livelli di “Rank” (Rank1 e Rank2),


ciascuno dotato di 8 Voice Palette (VoicePalette0 – VoicePalette7).
Importante anche la definizione della struttura tripletta (TRIP) relativa ad
ogni singola voce. Tale struttura è ripetuta per ogni sottovoce e risulta
definita nel file voicedata.h.

typedef struct Tripletta {


unsigned char Sysexcode;
char NomeVoce[LENGTH_OF_NAMES+1];
unsigned char orgPar t_exist;
unsigned char cc32;
unsigned char cc0;
unsigned char pc;
unsigned char volume;
unsigned char filter;
unsigned char micro_panpot;
unsigned char Panpot;
unsigned char voiceFamily;
char PoliphonicPriority;
unsigned char Env_Attack;
unsigned char Env_Decay;
unsigned char Env_Release;
unsigned char Env_Delay;
unsigned char RndTune_Probability;
unsigned char RndTune_MaxCents;
unsigned char pitch;
unsigned char pipe;
unsigned char outch;
unsigned char Dummy2[7];
char ShortNomeVoce[LENGTH_OF_SHORT_NAMES+1];
unsigned char volume_nbn[128];
unsigned char tone_nbn[128];
unsigned char pitch_nbn[128];
} TRIP;

Questa “Tripletta” contiene tutti i parametri di cui l‟ utente può effettuarne


l‟ editing. La maggior parte di essi sono definiti da un unico valore
numerico assegnabile da un range di valori ben predefinito. Altri sono
stringhe di testo editabili direttamente dall‟ utente con un numero massimo
di caratteri fissato. Infine è possibile evidenziare la presenza di parametri
caratterizzati da più valori memorizzati in vettori monodimensionali (es.
tone_nbn[128]).
Queste caratteristiche di diversificazione strutturale riscontrabili nella
gamma dei parametri modificabili sono alla base delle scelte operate nella
Graphic User Interface finale.

41
Capitolo 4
27 novembre 2008

Risulta logico come non tutti i parametri siano fisicamente implementabili


all‟ interno di unica finestra, ma vi sia la necessità di posizionarli su più
interfacce opportunamente interconnesse e accessibili agevolmente dall‟
utente.

4.3 – STANDARDIZZAZIONE MESSAGGIO MIDI

Rispettando la struttura principale di un sistema esclusivo, già illustrata


precedentemente, nella prima fase progettuale si è cercato di studiare la
soluzione migliore per il corretto invio delle informazioni allo strumento
elettronico fondamentali per l‟ accesso e la modifica dei parametri
strutturanti una singola voce . Si è giunti al seguente modello compositivo
del messaggio midi da impiegare per l‟ invio dei dati al Rodgers i538:

NUM ERO
INDICI VA LORI
F0 SYSEX OFFSET VA LORI CK F7
VOCE MODIFICATI
MODIFICATI

Figura 4.2 – Strutturazione standardizzata del messaggio midi da inviare allo


strumento elettronico per una corretta comunicazione.

I parametri standard già illustrati nella panoramica sul midi sono, l‟ F0 , il


sysexcode , il cecksum (CK) e l‟ F7 .
Come terzo dato si è deciso di inserire i 3 indici della matrice che
consentono l‟ accesso alla voce.
Poi l‟ OFFSET relativo all‟ indirizzo di memoria del parametro modificato.
Come quinto dato il nume ro dei valori modificati in quanto esistono
parametri che hanno più di un valore editabile (ad esempio volume_nbn ,
pitch_nbn); ciò contribuisce ad una allocazione dell‟ opportuno spazio (in
byte) in base al numero di dati effettivi da inviare.
Infine prima del cecksum vengono inseriti i VALORI MODIFICATI (da un
minimo di 1 ad un massimo di 128).
Tale strutturazione riflette un costruzione dinamica del sistema esclusivo
ottimizzando la comunicazione con l‟ hardware midi esterno.

42
Capitolo 4
27 novembre 2008

4.4 – PRESENTAZIONE DELL’ INTERFACCIA GRAFICA

Col supporto dei progettisti e sviluppatori dell‟ azienda Roland si è cercato


di analizzare quali fossero le soluzioni migliori nella creazione grafica della
GUI definitiva. Si è deciso di plasmare un‟ interfaccia che sia in grado di
selezionare univocamente una singola voce tra tutte quelle presenti sul
pannello principale, consentendo successivamente la scelta dei vari livelli di
“rank ” e “sottovoce” avvalendosi di appositi dispositivi di interfaccia.
L‟elevato numero di parametri e la loro sostanziale diversificazione hanno
indotto ad organizzare e presentare le funzionalità dell‟ applicazione su due
finestre indipendenti una dall‟ altra e direttamente accessibili dalla
interfaccia principale. Utilizzando uno stile di interazione per
manipolazione diretta l‟ utente agisce sui vari oggetti nello schermo tramite
l‟ utilizzo di tastiera e mouse. Il feedback dell„ interfaccia risulta rafforzato
dalla presenza di elementi interagenti di tipo attivo e reattivo ovvero in
grado di cambiare il loro aspetto e posizione a seconda dell‟ azione svolta
dall‟ utente.

Figura 4.2 – Finestra di dialogo principale da cui è possibile accedere alle 2


…………... finestre secondarie per l‟ editing dei parametri.

Le immagini delle tre finestre di dialogo principali evidenziano un perfetto


connubio tra funzionalità grafiche avanzate, stile di interazione semplice e

43
Capitolo 4
27 novembre 2008

sintesi delle possibilità di editig. L‟ accesso ai parametri di una singola


voce risulta notevolmente semplificato e velocizzato rispetto agli
innumerevoli passaggi di sottomenù occorrenti nello strumento reale. Le
funzionalità grafiche e i dispositivi d‟ interfaccia offerti dalla perfetta
integrazione tra MFC e ambiente di sviluppo Visual C++ hanno contribuito
alla creazione di un aspetto estetico attraente che si avvicina molto alle
sembianze dello strumento reale, agevolandone la comprensione e
l‟ utilizzo. La prima dialog si avvicina molto alle forme del pannello
anteriore reale del Rodgers i538 disponendo verticalmente le 3 sezioni di
voci principali; i pulsanti del pannello sono oggetti di tipo reattivo che
evidenziano la voce attualmente selezionata dall‟ utente con un colore rosso.
Nella parte destra della dialog principale si possono notare 3 dispo sitivi di
interfaccia di tipo combo box; i primi 2 offrono la possibilità di selezione i
vari livelli di “rank” e “voci secondarie”. Il terzo consente la scelta del
dispositivo su cui inviare il messaggio midi. Le 26 tipologie di parametri
editabili dall‟ utente appaiono facilmente visualizzabili nelle 2 dialog figlie
direttamente accessibili (dalla finestra principale) per mezzo dei pulsanti
EDIT_PAR_NOTA ed EDIT_PAR_VOCE. La disposizione ottimizzata di
vari elementi attivi ed inerti consente l‟ adozione di efficaci soluzioni
grafiche garantendo una ottima tolleranza agli errori ed una visione globale
dei parametri; essi risultano individuabili per mezzo di un nome ed uno o
più valori numerici rispettivamente raffigurati tramite un‟ etichetta e uno o
più editbox. Tutto ciò è stato possibile con l‟ utilizzo di opportuni costrutti
di programmazione software e grafica (tramite appositi editor grafici) le cui
potenzialità risultano evidenziabili soprattutto nella seconda dialog di
editing (Figura 4.2 ). La necessità di modificare 3 parametri di tipo vettore
caratterizzati da ben 128 elementi ciascuno ha contribuito all‟ ideazione
di una doppia tastiera virtuale costituita da 128 note totali. Adottando
altrettanti dispositivi di interfaccia di tipo bottone appare possibile
visualizzare i valori dei 3 parametri relativi alla nota selezionata
dall‟ utente.

44
Capitolo 4
27 novembre 2008

La modifica numerica di tutti i parametri risulta effettuabile con un


elemento d‟ interfaccia reattivo di tipo slider (figura 3.3) implementato all‟
interno di un‟ apposita dialog richiamabile dai pulsanti >EDITA< presenti
nelle due interfacce di editing.

Figura 4.3 – Dispositivo di interfaccia di tipo slider per la modifica del valore
numerico; essa risulta richiamabile col pulsante >EDITA< dalle 2 finestre di
editing.

Lo slider inoltre garantisce un „ottimo supporto alla tolleranza verso gli


errori dell‟ utente segnalando visualmente i valori massimo e minimo
assumibili dal parametro selezionato.
Ogni finestra (tranne quella principale) ha un‟ apposita funzione d‟ invio
delle modifiche effettuate con l‟ “impacchettamento” e la trasmissione delle
informazioni tramite protocollo midi; cliccando sull‟ elemento reattivo
SEND SYSEX l‟ utente è in grado di comunicare all‟ hardware esterno le
variazioni apportate alla voce in editing.
La finestra di dialogo principale consente l‟ accesso ad una ulteriore
interfaccia le cui funzionalità sono totalmente indipendenti dalle
caratteristiche di editor grafico analizzate finora. Il pulsante SELEZIONE
VOCI MULTIPLE effettua l‟ apertura di una dialog per la selezione multi-
timbrica dell‟ intero elenco di voci (APPENDICE D) caratterizzanti il
Rodgers i538. Per tale scopo si è ritenuta opportuna l‟ implementazione di
un particolare dispositivo d‟ interfaccia reattivo che consentisse una veloce
visualizzazione e multi selezione delle 244 voci totali. Le potenzialità delle
MFC hanno permesso l‟ ideazione di una lista di elementi reattivi fruibile
rapidamente con una scroll bar laterale.

45
Capitolo 4
27 novembre 2008

Figura 4.3 – Finestra di dialogo che consente la selezione multi timbrica delle 244
voci.

Ciascun bottone è caratterizzato da un nome della voce ad esso relazionata e


da un led laterale. L‟ interazione con l‟ utente è attuabile con lo
spegnimento o l’ accensione del led corrispondente all‟ elemento cliccato
ottenendo un risultato esteticamente gradevole e funzionalmente comodo. L‟
interfaccia opera anche l‟ invio del messaggio midi ad ogni azione dell‟
utente, attivando o disattivando il bit relativo all‟ ultima voce selezionata.

46
Capitolo 5
27 novembre 2008

5. - COSTRUZIONE INTERFACCIA GRAFICA

5.1 – PANORAMICA DAL RESOURCE VIEW

Il visualizzatore di risorse presente nell‟ ambiente di sviluppo Visual C++ mette in


evidenza le 5 finestre di dialogo costituenti l‟ interfaccia grafica ideata
individuabili da un proprio nome di progetto (IDD_nome_della _dialog).

Figura 5.1 – Elenco delle 5 Dialog di progetto visualizzabili dal Developer Studio.

Nella tabella seguente ne vengono descritte le singole caratteristiche funzionali ed


estetiche.

NOME_DIALOG Descrizione
Finestra relat iva all‟ ed iting dei parametri
dei 3 parametri di tipo vettore modificali
IDD_ DIALOG_ NOTA tramite l‟ imp lementazione grafica d i una
tastiera virtuale costituita da 128 tasti
musicali.

Finestra relativa a ll‟ editing di 23


parametri indiv iduabili per mezzo d i un
IDD_ DIALOG_PAR nome ed uno o più valori nu merici
rispettivamente raffigurati tramite un‟
etichetta e uno o più edit-box.

Finestra relat iva al dispositivo di


interfaccia di t ipo slider per la modifica del
IDD_ DIALOG_SLIDER valore numerico; essa risulta rich iamabile
col pulsante >EDITA< dalle 2 dialog
precedenti.

47
Capitolo 5
27 novembre 2008

Finestra principale dell‟ interfaccia che


opera l‟ accesso alle voci dello strumento e
successivamente a tutte le altre dialog di
editing e multi selezione. Il suo aspetto
grafico ricrea le semb ianze del pannello
IDD_ RODGERS_i385_GUI_ DIALOG
principale dell‟ o rgano liturgico favorendo
l‟ interazione con l‟ utente.

Finestra relativa alla lista di bottoni che


consente una veloce visualizzazione e
IDD_S ELEZIONE_ VOCI_ MULTIPLE mu lti selezione delle 244 voci totali. Le
voci attive vengono individuate dalla
accensione del corrispondente led.

Di seguito vengono riportate la lista dei file .cpp e .h sviluppati nel Visual C++ e
l‟ elenco delle immagini utilizzate nelle creazioni grafiche dell‟ intera interfaccia.

Figura 5.2 – Lista dei file .cpp e .h sviluppati nel Visual C++ e l‟ elenco .delle immagini
utilizzate nelle creazioni grafiche dell‟ intera interfaccia.

48
Capitolo 5
27 novembre 2008

5.2 – DIALOG PRINCIPALE : IDD_RODGERS_i385_GUI_DIALOG

Il codice C++ per la costruzione della finestra di dialogo principale risulta definito
nel file RODGER_i385_GUIDlg.cpp; ad essa è stato assegnato il nome
identificativo: IDD_RODGERS_i385_GUI_DIALOG.
Dal editor grafico del Visual C++ è possibile visionarne la composizione
individuando i diversi dispositivi d‟ interfaccia integrati tramite l‟ apposito GUI
designer tipico dell„ ambiente di sviluppo usato.

Figura 5.3 – Composizione strutturale della dialog principale con l‟ utilizzo di


………………...elementi attivi e reattivi d‟ interfaccia.

Compaiono:
 26 Pulsanti “ON” che consentono la selezione della rispettiva voce
 2 Combo_Box che permettono la selezione del Rank e della Voice Palette
 1 Combo_Box realitava alla selezione del Device_Midi
 2 Pulsanti che aprono le 2 Dialog di visualizzaione dei parametri
editabili.
 1 Pulsante che opera l‟ accesso alla dialog di multi selezione (senza
editing) di più voci.

49
Capitolo 5
27 novembre 2008

Prima di poter effettivamente sfruttare tali elementi attivi e reattivi d‟ interfaccia


per l‟ editing della voce desiderata, appare evidente la necessità di un accesso
diretto alla struttura delle voci (residente nel file baroque.cpp); in un calcolatore
ciò risulta possibile operando il caricamento dei dati da modificare in RAM.
Ciò risulta svolto opportunamente attraverso la funzione CaricaBaroqueRom()
in cui avviene l' inizializzazione dei dati in Ram tramite una matrice di strutture
costanti (baroque_ROM). All‟ intero del file risulta dichiarata globalmente una
struttura TRIP del tipo:

g_dati_RAM[NUMBER_OF_TIMBRES][COUPLED_VOIC ES][NUMBER_OF_VOICES];

In seguito nella CRODGERS_i385_GUIDlg::OnInitDialog() avviene la


inizializzazione della funzione CaricaBaroqueRom() caratterizzata dal seguente
codice:

void CRODGERS_i385_GUIDlg::CaricaBaroqueRom()
{
int i , j, k ;

for (i=0 ; i<=NUMBER_OF_TIMBRES; i++)


{
for (j=0 ; j<=COUPLED_VOIC ES; j++)
{
for (k=0 ; k<=NUMBER_OF_VOIC ES; k++)
{

g_dati_RAM[i][j][k] = baroque_ROM[i][j][k];
}
}
}

return;
}

Le voci principali (ognuna corrispondente ad un pulsante del pannello frontale del


RODGERS) sono 26 suddivise in 3 sezioni :
 PEDAL
 MANUAL I
 MANUAL II
Per tale motivo si è scelto di ricreare un‟ interfaccia simile a quella del pannello
frontale posizionando 26 pulsanti suddivisi su 3 livelli in base al gruppo di
appartenenza. Tali elementi vengono dichiarati nel RODGERS_i385_GUIDlg.h

50
Capitolo 5
27 novembre 2008

come elemetni reattivi di tipo CBitmapButton in quanto permettono il


caricamento di immagini sulla superficie del bottone.

CBitmapButton m_Button_ON1;


CBitmapButton m_Button_ON26;

La gestione dell‟ evento di Click tramite mouse su ogni singolo pulsante è stata
possibile con l‟ utilizzo del ClassWizard, associando ad ogni tasto il tipo di
messaggio ON_BN_CLICKED secondo la seguente mappatura:

ON_BN_CLICKED(IDC_ON1, OnOn1)


ON_BN_CLICKED(IDC_ON26, OnOn26)

L‟ evento di click su un tasto (del pannello virtuale) richiama automaticamente la


corrispondete funzione membro OnOn1 … OnOn26; di seguito il codice c++
corrispondente (al primo elemento attivo di tipo pulsante):

void CRODGERS_i385_GUIDlg::OnOn1()
{
ModificaTab(0);
timbre = 0;

m_cEdButtonParVoce.EnableWindow(TRUE);
m_cEdButtonParNota.EnableWindow(TRUE);
}

Tale funzione membro attiva la chiamata della ModificaTab() passando come


parametro il numero identificativo del pulsante selezionato (progressivamente da
0 a 25); in essa inoltre si evidenzia un‟ operazione fondamentale per il
collegamento parametrico delle varie dialog dell‟ applicativo. Compare, infatti, l‟
assegnazione dell‟ ID del pulsante cliccato alla variabile globale timbre ovvero
una delle 26 voci di registro principali; si è quindi ottenuto il primo indice della
matrice delle voci.
I pulsanti d‟ accesso alle 2 dialog di editing risultano disabilitati ( ovvero si
trasformano da elementi inerti a elementi attivi) fino a quando l‟ utente non
effettua la selezione della voce principale. Tale abilitazione dinamica è attivabile

51
Capitolo 5
27 novembre 2008

implementando la funzione EnableWindow(TRUE) nella variabile membro


associata ai 2 bottoni.
Ciò è riscontrabile in tutte le 26 funzioni membro collegate alle voci principali
evincibile dal seguente codice di programmazione :

void CRODGERS_i385_GUIDlg::OnOn2()
{
ModificaTab(1);
timbre = 1;

m_cEdButtonParVoce.EnableWindow(TRUE);
m_cEdButtonParNota.EnableWindow(TRUE);
}


void CRODGERS_i385_GUIDlg::OnOn26()
{
ModificaTab(25);
timbre = 25;

m_cEdButtonParVoce.EnableWindow(TRUE);
m_cEdButtonParNota.EnableWindow(TRUE);
}

52
Capitolo 5
27 novembre 2008

5.2.1 – DESCRIZIONE DELLA FUNZIONE: MODIFICATAB( )

Codice relativo alla prima parte della funzione:

void CRODGERS_i385_GUIDlg::ModificaTab(int tab)


{
int i;
int curr_rank=0;
CString str;
str.Empty();

m_cCmbRank.ResetContent();
m_cCmbPalette.ResetContent();

str.Format(_T(g_dati_RAM[tab][1][0].NomeVoce));
if( str!="Vuoto ")
{
curr_rank=1;
}

Tale funzione membro innanzitutto resetta il contenuto delle ComboBox relative


al Rank e alla Voice Palette; successivamente verifica se la voce principale
(corrispondente all‟ indice intero “tab” passato come parametro) è dotata anche
del Rank 1 (ovvero un secondo livello di Rank), altrimenti viene rilevato un unico
valore selezionabile (nella combo corrispondente) di Rank 0. Per far ciò viene
verificato se il NomeVoce del primo elemento (0) del livello di rank [1] nel
registro principale selezionato [tab] sia una stringa corrispondente a “Vuoto” (di
conseguenza per costruzione anche tutte le successive sono Vuote). Se non si
verifica tale condizione allora risulta settato ad 1 il valore del current_rank attuale.

for ( i=0 ; i<=curr_rank; i


{
str.Format(_T("rank % d"),i);
m_cCmbRank.AddString(str);
}
m_cCmbRank.SetCurSel(0);

for ( i=0 ; i<NUMBER_OF_VOICES ; i


{
str.Format("% s",_T(g_dati_RAM[tab][0][i].NomeVoce));

if( str!="Vuoto ")


{
m_cCmbPalette.AddString(str);
}
}
m_cCmbPalette.SetCurSel(0);
}

53
Capitolo 5
27 novembre 2008

Nella seconda parte vengono riempite le combo box Rank e VoicePalette; la


prima considerando se la voce è dotata anche del rank 1 e la seconda (voice
palette) col campo NomeVoce fino a quando non viene rilevata una stringa vuota.

5.2.2 – ELEMENTI COMBO BOX: RANK E VOICE PALETTE

void CRODGERS_i385_GUIDlg::OnSelchangeComboRank()

{
int i;
int selection = m_cCmbRank.GetCurSel();
coupled = selection;

Il metodo OnSelchange relativo alla combo box permette di intercettare l’ evento


di selezione di un elemento (all‟ interno del menù a tendina della combo) da parte
dell‟ utente. La funzione GetCurSel() permette di memorizzare la selezione all‟
interno della varibile selection successivamente assegnata alla variabile globale
coupled (rappresenta il secondo indice della matrice g_dati_ram[][][]).

m_cCmbPalette.ResetContent();

for ( i=0 ; i<NUMBER_OF_VOICES ; i++)


{
str.Format("% s",_T(g_dati_RAM[timbre][selection][i].NomeVoce));

if( str!="Vuoto ")


{
m_cCmbPalette.AddString(str);
}
}
m_cCmbPalette.SetCurSel(0);

La selezione del Rank provoca anche il cambiamento degli elementi della Combo
Voice Palette; dopo il suo reset tale combo viene riempita con gli elementi
NomeVoce in base alla variabile globale timbre e alla selection (rank selezionato)
con un indice i di scorrimento. Alla fine viene settato di default il primo elemento.

void CRODGERS_i385_GUIDlg::OnSelchangeComboPalette
{
int selection = m_cCmbPalette.GetCurSel();
voice = selection;

54
Capitolo 5
27 novembre 2008

La selezione di un elemento all‟ interno della combo Voice Palette permette la


memorizzazione di tale valore nella variabile globale voice (terzo indice della
matrice voci).

5.2.3 – ELEMENTO COMBO BOX: MIDI DEVICE

Nella funzione membro ::OnInitDialog() avviene la definizione della combo box


relativa alla selezione del MIDI DEVICE, ovvero della periferica midi da
utilizzare per operare una corretta comunicazione tra l‟ interfaccia grafica e lo
strumento elettronico esterno collegato.

m_cCmbMidiDevice.ResetContent();

int num_dev = midiOutGetNumDevs();

for (int i=0 ; i<=num_dev; i++)


{
str.Format(_T("Midi Device % d"), i);
m_cCmbMidiDevice.AddString(str);
}
m_cCmbMidiDevice.SetCurSel(0);

Le librerie di sistena windows.h e mmsystem.h permettono di utilizzare delle


apposite funzioni per la gestione dei messaggi e delle periferiche midi. In questo
caso si è utilizzata la funzione midiOutGetNumDevs() che restituisce come
valore di ritorno il numero di periferiche midi di Output presenti nel sistema e
viene assegnato alla variabile num_dev. La combo risulta riempita tramite un
ciclo for creando la visualizzazione di un elenco indicante MidiDevice 0 ,
MidiDevice 1 , … .

int selection = m_cCmbMidiDevice.GetCurSel();


midi_device = selection;

La selezione di un midi device viene assegnata alla variabile globale


midi_device.

55
Capitolo 5
27 novembre 2008

5.2.4 – ELEMENTI GRAFICI

La possibilità di caricare immagini di background e sulla superficie dei vari


pulsanti permette di dare una visione molto più gradevole e precisa alla dialog
principale ricreando l‟ aspetto del pannello principale dello strumento elettronico
reale.

Figura 5.4 – Composizione strutturale della dialog principale con l‟ utilizzo di elementi
attivi e reattivi d‟ interfaccia sfruttando le possibilità di integrazione grafica tramite il
caricamento di immagini di background e sulla superfice dei vari oggetti d‟ interfaccia.

L‟ implementazione della bitmap di background nell‟ intera dialog è effettuata


tramite il metodo OnPaint caratterizzato dal seguente codice:

void CRODGERS_i385_GUIDlg:: OnPaint()


{
CPaintDC dc( this);
CBitmap bitmap;
CDC memdc;

bitmap.LoadBitmap( IDB_BACK_SEL_VOCE );
BITMAP bmp;
bitmap.GetBitmap( &bmp );
memdc.CreateCompatibleDC( &dc );
memdc.SelectObject( &bitmap );

CRect rect;
GetClientRect(rect);

56
Capitolo 5
27 novembre 2008

StretchBlt (dc.m_hDC,0, 0, rect.r ight, rect.bottom, memdc.m_hDC, 0, 0, bmp.bmWidth,


bmp.bmHeight, SRCCOPY );
}

Si parte dalla definizione di una variabile dc di tipo CPaintDC ovvero di tipo


device context e viene inizializzata tramite un puntatore all‟ oggetto corrente
(this). La classe CPaintDC richiama automaticamente le funzioni API necessarie
affinchè ogni applicazione Windows possa disegnare un qualsiasi elemento
grafico.
La classe CBitmap permette un controllo completo su una bitmap. Si definisce lo
oggetto bitmap su cui carichiamo l‟ immagine desiderata (esplicitando il nome del
suo ID assegnato nelle risorse del developer studio). Si crea poi un secondo
device context di tipo CDC su cui caricare la bitmap, che viene reso compatibile
col device context principale; successivamente tramite la funzione SelectObject()
si seleziona la bitmap nel nuovo DC. Successivamente, dopo aver determinato l‟
area disponibile
(la quale assume la forma di un rettangolo), l‟ immagine viene copiata dal
secondo context a quello principale attraverso la funzione StretchBlt che ne
consente anche un ridimensionamento.
Per quanto riguarda, invece, il caricamento di bitmap sulla superficie dei pulsanti
per la selezione delle voci principali, si è sfruttata la proprietà Owne r Draw e i
messaggi per gli eventi del mouse (click, rilascio … ) definiti dai metodi di
Windows: WM_LBUTTONDOWN e WM_LBUTTONUP.

m_Button_ON1.LoadBitmaps(IDB_UP, IDB_DOWN , IDB_FOCUS, ID B_DISABLE);




m_Button_ON26.LoadBitmaps(IDB_UP, IDB_DOWN , IDB_FOCUS,IDB_DISABLE);

Come si può evincere dal codice la variabile di controllo associata ad ogni


pulsante (m_Button_ONx) richiama il metodo LoadBitmaps(); quest‟ ultima
funzione permette di caricare 4 immagini tramite il loro ID. Nel nostro caso sono:

57
Capitolo 5
27 novembre 2008

IDB_UP IDB_DOWN IDB_FOCUS IDB_DISABLE

(bianco) (bianco)

Pulsante rilasciato
Pulsante non Pulsante in fase di (effettuata la Pulsante
cliccato click (schiacciato) selezione) disabilitato

Evidente come quello più importante (nel nostro caso) sia il FOCUS che permette
di mantenere evidenziata la voce di registro principale selezionata (mentre gli
altri 25 pulsanti restano di default bianchi).

5.2.5 – PULSANTI EDIT_PAR_VOCE ED EDIT_PAR_NOTA

void CRODGERS_i385_GUIDlg::OnButtonEditParVoce()
{
CEditParDlg dlg;
dlg.DoModal();
return;
}

void CRODGERS_i385_GUIDlg::OnButtonEditParNota()
{
CEditParNotaDlg dlg;
dlg.DoModal();
return;
}

I 2 metodi associati al click di tali pulsanti aprono le 2 dialog relative all‟ editing
di tutti i parametri della voce selezionata; segue il codice relativo anche al
caricamento delle apposite bitmaps sulla lora superficie grafica.

m_cEdButtonParVoce.LoadBitmaps(IDB_EDIT_VOCE_UP, IDB_EDIT_VOCE_DOWN ,
IDB_EDIT_VOCE_UP, IDB_EDIT_NOTA_DISABLE);


m_cEdButtonParNota.LoadBitmaps(IDB_EDIT_NOTA_UP, IDB_EDIT_NOTA_DOWN ,
IDB_EDIT_NOTA_UP, IDB_EDIT_NOTA_DISABLE);

58
Capitolo 5
27 novembre 2008

5.3 – DIALOG EDIT PARAMETRI VOCE: IDD_DIALOG_PAR

Figura 5.4 – Composizione strutturale della dialog per la modifica di 23 parametri. 21


sono tipo numerico ed editabili tramite lelemento d‟ interfaccia >EDITA<. Gli altri 2 sono
stringhe di testo modificabili direttamente dal dispositivo di input di tipo tastiera.

Lo stile di interazione a manipolazione diretta consente all‟ utente, in tale finestra,


di effettuare l‟ editing su 23 parametri caratteristi della voce selezionata nell‟
interfaccia principale basandosi sui 3 indici della matrice voci g_dati_Ram[][][].
La “costruzione” di tale finestra utente è implementata nei file EditParDlg.cpp e
EditParDlg.h. Ad ogni parametro risulta associato un elemento inerte di tipo edit-
box (casella di testo) visualizzante il valore corrispondente. Nell maggior parte dei
casi si tratta di un valore numerico , mentre i 2 parametri “NOME VOCE” e
“SHORT NOME VOCE” sono costituiti da una stringa di testo di lunghezza ben
definita (è possibile l‟ inserimento di un numero massimo di caratteri).
Altra eccezione è rappresentata dal parametro “DUMMY[7]” che, essendo un
vettore, richiede la visualizzazione dei sui 7 elementi su altrettante caselle di testo.

CString m_cEdNomeVoce;
CString m_cEdSysexCode;
CString m_cEdOrgPart_Exist;
CString m_cEdControlChange32;
CString m_cEdControlChange0;
CString m_cEdProgramChange;

59
Capitolo 5
27 novembre 2008

CString m_cEdVolume;
CString m_cEdFilter;
CString m_cEdMicroPanpot;
CString m_cEdPanpot;
CString m_cEdVoiceFamily;
CString m_cEdPoliphonicPriority;
CString m_cEdEnvAttack;
CString m_cEdEnvDecay;
CString m_cEdEnvRelease;
CString m_cEdEnvDelay;
CString m_cEdRandomTuneProbability;
CString m_cEdRandomTuneMaxCents;
CString m_cEdPitch;
CString m_cEdPipe;
CString m_cEdOutch;
CString m_cEdDummy0;

CString m_cEdDummy6;
CString m_cEdShortNomeVoce;

Come si può evincere dal codice estratto dal file header corrispondente, ad ogni
parametro è assegnata una variabile (membro) di controllo di tipo CString. Per i 2
parametri stringa l‟ editing viene effettuato direttamente immettendo o cambiando
caratteri da tastiera. Per tutti gli altri, che assumono principalmente valore
numerico da 0 a 128 , la modifica può essere effettuata cliccando sul
corrispondente pulsante “EDITA”, attraverso l‟ apertura di un‟ apposita finestra
di editing (le cui caratteristiche verranno specificate in seguito). Ogni bottone di
edit è stato identificato con un opportuno ID evidenziando in modo univoco il
parametro a cui risulta associato. Con il ClassWizard, successivamente, ad ogni
tasto è stato associato il tipo di messaggio ON_BN_CLICKED secondo la
seguente mappatura:

ON_BN_CLICKED(IDC_BUTTON_SYSEX, OnButtonSysex)
ON_BN_CLICKED(IDC_BUTTON_ORGPARTEX, OnButtonOrgpar tex)
ON_BN_CLICKED(IDC_BUTTON_CC32, OnButtonCc32)
ON_BN_CLICKED(IDC_BUTTON_CC0, OnButtonCc0)
ON_BN_CLICKED(IDC_BUTTON_PC, OnButtonPc)
ON_BN_CLICKED(IDC_BUTTON_VOLUME, OnButtonVolume)
ON_BN_CLICKED(IDC_BUTTON_FILTER, OnButtonFilter)
ON_BN_CLICKED(IDC_BUTTON_MICRO_PANPOT, OnButtonMicroPanpot)
ON_BN_CLICKED(IDC_BUTTON_PANPOT, OnButtonPanpot)
ON_BN_CLICKED(IDC_BUTTON_VOICE_FAMILY, OnButtonVoiceFamily)
ON_BN_CLICKED(IDC_BUTTON_POLIPHONIC_PRIORITY, OnButtonPoliphonicPriority)
ON_BN_CLICKED(IDC_BUTTON_ENV_ATTACK, OnButtonEnvAttack)
ON_BN_CLICKED(IDC_BUTTON_ENV_DECAY, OnButtonEnvDecay)
ON_BN_CLICKED(IDC_BUTTON_MICRO_ENV_RELEASE, OnButtonMicroEnvRelease)
ON_BN_CLICKED(IDC_BUTTON_ENV_DELAY, OnButtonEnvDelay)
ON_BN_CLICKED(IDC_BUTTON_RANDOM_TUNE_PROB, OnButtonRandomTuneProb)

60
Capitolo 5
27 novembre 2008

ON_BN_CLICKED(IDC_BUTTON_RANDOM_TUNE_MAXCENTS, OnButtonRandomTunMaxcents)
ON_BN_CLICKED(IDC_BUTTON_PITCH, On ButtonPitch)
ON_BN_CLICKED(IDC_BUTTON_PIPE, OnButtonPipe)
ON_BN_CLICKED(IDC_BUTTON_OUTCH, OnButtonOutch)
ON_BN_CLICKED(IDC_BUTTON_DUMMY_0, OnButtonDummy0)

ON_BN_CLICKED(IDC_BUTTON_DUMMY_6, OnButtonDummy6)

5.3.1 – SPECIFICHE: ONINITDIALOG( )

BOOL CEditParDlg::OnInitDialog()
{
CDialog::OnInitDialog();

m_cEdSysexCode.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].Sysexcode));


m_cEdNomeVoce.For mat("% s",_T(g_dati_RAM[timbre][coupled][voice].NomeVoce));
m_cEdOrgPart_Exist.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].orgPar t_exist));
m_cEdControlChange32.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].cc32));
m_cEdControlChange0.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].cc0));
m_cEdProgramChange.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].pc));
m_cEdVolume.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].volume));
m_cEdFilter.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].filter));
m_cEdMicroPanpot.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].micro_panpot));
m_cEdPanpot.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].Panpot));
m_cEdVoiceFamily.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].voiceFamily));
m_cEdPoliphonicPriority.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].PoliphonicPriority ));
m_cEdEnvAttack.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].Env_Attack));
m_cEdEnvDecay.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].Env_Decay));
m_cEdEnvRelease.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].Env_Release));
m_cEdEnvDelay.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].Env_Delay));
m_cEdRandomTuneProbability.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].
RndTune_Probability));
m_cEdRandomTuneMaxCents.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].
RndTune_MaxCents));
m_cEdPitch.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].pitch));
m_cEdPipe.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].pipe));
m_cEdOutch.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].outch));
m_cEdDummy0.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].Dummy2[0]));

m_cEdDummy6.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].Dummy2[6]));
m_cEdShortNomeVoce.For mat("% s",_T(g_dati_RAM[timbre][coupled][voice].Shor tNomeVoce)

UpdateData(FALSE);
return TRUE;
}

La fase di inzializzazione della Dialog richiede il corretto caricamento dei valori


nelle caselle di testo relativamente a tutti i parametri visualizzati. Tale operazione
è possibile tramite le 3 variabili globali (timbre, coupled, voice) memorizzate
attraverso la Dialog principale, e che operano l‟ accesso nella matrice generica di

61
Capitolo 5
27 novembre 2008

voci (g_dati_RAM) ai campi corrispondenti. Il valore correlato ad ogni parametro


viene formattato, memorizzato nella rispettiva variabile di controllo e visualizzato
nella casella di testo dell‟ interfaccia grafica.

5.3.2 – MODIFICA DEI PARAMETRI

Ad ogni parametro viene associata la corrispondente funzione membro (secondo il


codice precedentemente illustrato) con cui realizzare l‟ editing del suo valore.
Di seguito il codice relativo alle prime 2 funzioni membro presenti nel file .cpp di
sviluppo in quanto le successive hanno tutte l‟ identica struttura.

void CEditParDlg::OnButtonSysex()
{

CSLIDERDlg dlg;
min_range = 0;
max_range = 255;
p = &g_dati_RAM[timbre][coupled][voice].Sysexcode;
if(dlg.DoModal() == ID_BUTTON_SLIDER_MODIFICA)
{
m_cEdSysexCode.For mat("% ld", *p);
UpdateData(FALSE);
}
return;
}

void CEditParDlg::OnButtonOrgpartex()
{

CSLIDERDlg dlg;
min_range = 0;
max_range = 127;
p = &g_dati_RAM[timbre][coupled][voice].orgPar t_exist;
if(dlg.DoModal() == ID_BUTTON_SLIDER_MODIFICA)
{
m_cEdOrgPart_Exist.For mat("% ld", *p);
UpdateData(FALSE);
}
return;
}

Nella funzione membro viene aperta una istanza della CSLIDERDlg (dialog per l'
editing del parametro selezionato), successivamente si fissano i range massimo e
minimo nelle rispettive variabili globali necessarie per l' utente e per la funzione

62
Capitolo 5
27 novembre 2008

opportuna affinchè si possa fissare (in fase di editing) un corretto valore tra quelli
assumibili dal parametro stesso.
Importante anche l' assegnazione dell' indirizzo del campo relativo alla quantità
in editing alla varibile globale p; tale puntatore passato alla dialog CSLIDERDlg
si caratterizza come l' unico modo per identificare e modificare correttamente il
campo della matrice g_dati_RAM[][][] contenente il valore da editare.
Il codice nella parte finale permette di aggiornare il valore della varibile di
controllo (e quindi del parametro) quando l' utente decide di confermare la
modifica effettuata nell' apposita Dialog (CSLIDERDlg) per cui, tramite il
"puntatore globale" p, si può facilmente aggiornarne il valore nella finestra di
origine (che altrimenti, senza tale operazione, avrebbe visualizzati i "vecchi"
valori senza update).

5.3.3 – INVIO MESSAGGIO MIDI

Tutto ciò che riguarda la costruzione, l‟ impiego delle idonee API di windows per
la corretta organizzazione del messaggio e per l‟ utilizzo del Device selezionato, e
quindi l‟ invio midi finale è contenuto nella funzione membro :

void CEditParDlg::MakeSysex (unsigned char *pValue , int dim)

Il midi exclusive message deve rispettare lo standard Roland sviluppato e


specificato nelle prime fasi dell‟ intero progetto secondo la seguente struttura (già
illustrata):

NUM ERO
INDICI VA LORI
F0 SYSEX OFFSET VA LORI CK F7
VOCE MODIFICATI
MODIFICATI

Essa risulta costituita da una serie di byte opportunamente “impacchettati” su un‟


idonea disposizione di base possibile tramite la dichiarazione del seguente Array:

unsigned char midi_array[300];

costituito da 300 elementi di tipo unsigned char (1 byte). Analizziamo ora più
approfonditamente la parte di codice riguardante la MakeSysex.

63
Capitolo 5
27 novembre 2008

void CEditParDlg::MakeSysex (unsigned char *pValue , int dim)


{
Tale funzione riceve come parametro l‟ indizzo (*pValue) della quantità in
editing e il numero (in byte) dim di valori assumibili.

int i , sum ,ck ,w ;


short offset;
unsigned char midi_array[300];
int midipor t;
HMIDIOUT device;

Tra le dichiarazioni di variabili interne alla funzione membro spiccano:


la variale device di tipo HMIDIOUT che identifica l‟ interfaccia midi
device per i messaggi midi in uscita
la variabile midiport che seleziona la porta midi di uscita da aprire e
quindi da utilizzare

offset = pValue - &g_dati_RAM[timbre][coupled][voice].Sysexcode;

Nei 2 byte costituenti la varibile offset viene memorizzata la differenza di


indirizzo di memoria tra il puntatore al valore del parametro corrente (pValue) e il
primo elemento della struttura della voce in editing (Sysexcode).
Ad esempio se si sta editando il parametro g_dati_RAM[21][0][4]. filter la
variabile offset assumerà il seguente valore:

&g_dati_RAM[21][0][4].filter - &g_dati_RAM[21][0][4].Sysexcode;

ovvero la differenza di indirizzo tra il parametro filter e il primo parametro della


stessa voce di registro.

//MESSAGGIO MIDI
midi_array[0] = 0xF0;
midi_array[1] = 0x41;
midi_array[2] = 0x10;
midi_array[3] = 0x30;
midi_array[4] = 0x12;

midi_array[5] = timbre;
midi_array[6] = coupled;
midi_array[7] = voice;

Nella costruzione del messaggio midi_array[] viene specificato il valore


esadecimale da assegnare ad ogni byte partendo dall‟ F0 (inizio messaggio

64
Capitolo 5
27 novembre 2008

esclusivo) proseguendo con i successivi byte dall‟ elemento 1 al 4 che


caratterizzano il messaggio esclusivo. Nei bytes 5-7 vengono disposti
rispettivamente gli indici di accesso alla matrice delle voci principali.
Da sottolineare il fatto che nei messaggi esclusivi gli unici bytes che possano
assumere come bit significativo 1 sono esclusivamente il primo e l‟ ultimo (F0 -
F7) all‟ interno del Midi Exclusive Message.
In tutti gli altri possiamo avere al massimo una configurazione di bit del tipo
01111111 corrispondete ad un range di valori compreso tra 0 e 127.
Come verrà in seguito illustrato si dovranno implementare delle opportune
operazioni su bit per poter trattare valori superiori a 127.

#ifdef INTEL_TYPE
midi_array[11] = (char) (offset & 0x000F) ;
midi_array[10] = (char) ((offset & 0x00F0) >> 4);
midi_array[9] = (char) ((offset & 0x0F00) >> 8);
midi_array[8] = (char) ((offset & 0xF000) >> 12);
#else
midi_array[8] = (char) (offset & 0x000F) ;
midi_array[9] = (char) ((offset & 0x00F0) >> 4);
midi_array[10] = (char) ((offset & 0x0F00) >> 8);
midi_array[11] = (char) ((offset & 0xF000) >> 12);
#endif

Il parametro di offset valorizzato su 2 byte viene splittato opportunamente con


nibble (unità di misura per indicare quattro bit) su 4 byte. I primi 4 bit più
significativi vengono splittati a destra di 12 bit ed assegnanti al byte 8. Le stesse
operazioni di “and” logico e “splittin”g di bit vengono impiegate per i successivi 3
nibble.
Come sappiamo le operazioni di immagazzinamento in memoria dei dati superiori
al byte vengono interpretate in modo diverso a seconda del calcolatore utilizzato.
E‟ questa la cosiddetta problematica Big-endian e little-endian :

Big-endian è la memorizzazione che inizia dal byte più significativo per


finire col meno significativo; è utilizzata dai processori Motorola
Little-endian è la memorizzazione che inizia dal byte meno significativo
per finire col più significativo; è utilizzata dai processori Intel

65
Capitolo 5
27 novembre 2008

Nel nostro caso tramite la #define INTEL_TYPE e il costrutto #ifdef - #else si è


potuta interpretare correttamente tale problematica operando prima una
memorizzazione dal byte più significativo e nel secondo caso da quello meno
significativo.

midi_array[12] = dim;
for (i=0; i<=dim-1; i++)
{
midi_array[13+i] = *pValue++;
}

In base al numero di valori (dim) da inviare tramite il messaggio midi vengono


riempiti gli elementi dell‟ array successivi al 12, attraverso il ciclo for che assegna
ogni valore successivo, sfruttando il puntatore al primo elemento incrementato di
1 ad ogni iterazione.

um = 0;
for (w=5 ; w <=13 + (dim-1) ; w++)
{
sum += midi_array[w] ;
}

ck = (128 - sum) & 0x7F;

midi_array[13+dim] = ck;
midi_array[13+dim+1] = 0xF7;

Nella parte finale del messaggio midi viene calcolato il checksum ovvero una
somma di controllo. Si tratta di una sequenza di bit che risulta utilizzata per
verificare l'integrità del messaggio sommando tutti i byte dall‟ elemento subito
dopo i bytes che identificano l‟ exclusive message. fino a quello che identifica
l‟ ultimo dei valori assumibili dal parametro. Il checksum risulta memorizzato nel
penultimo elemento prima dell‟ F7 finale nel midi_array[]. Per controllare
l'integrità del messaggio in ricezione sarà sufficiente effettuare la stessa
operazione di somma e confrontarla con il checksum memorizzato. Se i due valori
coincidono, i dati possono essere considerati integri.

La funzione MakeSysex implementa anche la parte di codice con cui vengono


richiamate le opportune funzioni API necessarie al sistema per l‟ interazione col

66
Capitolo 5
27 novembre 2008

device selezionato consentendo l‟ aperture delle porte midi ed inviando


correttamente l‟ Exclusive Midi Message. Eccone il codice relativo:

midipor t = midi_device;
MIDIHDR* pHeader = new MIDIHDR;
pHeader->lpData = (char *) &midi_array[0];
pHeader->dwBufferLength = 200;
pHeader->dwBytesRecorded = (13+dim+1);
pHeader->dwFlags=0;

La libreria Windows Multimedia definisce la struttura MIDIHDR nel seguente


modo:

typedef struct midihdr_tag {


LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBy tesRecorded;
DWORD_PTR dwUser;
DWORD dwFlags;
struct midihdr_tag * lpNext;
DWORD_PTR reserved;
DWORD dwOffset;
DWORD_PTR dwReserved[4];
} MIDIHDR, *LPMIDIHDR;

Definendo il puntatore pHeader ad una nuova struttura di questo tipo possiamo


caratterizzarne i vari elementi come definito nel codice illustrato :

lpData definisce il puntatore al messaggio midi da inviare che nel nostro


caso è il midi_arraa[]. Viene assegnato infatti l‟ indirizzo del primo
elemento dell‟ array.
Si definisce la grandezza del buffer di “lettura” del messaggio midi pari a
200.
Si definisce la grandezza attuale dei dati da “bufferizzare” in base al
numero dei valori del parametro considerato : 13+dim+2.

In seguito si utilizzano le funzioni API Midi idonee:

midiOutOpen(&device, midipor t, 0, 0, CALLBACK_NULL);

Tramite le varibili device e midiport si effettua l‟ apertura della porta midi


selezionata (combo_midi_device).

67
Capitolo 5
27 novembre 2008

midiOutPrepareHeader(device , (LPMIDIHDR) pHeader, sizeof(MIDIHDR));

La funzione prepara il Messaggio Midi per l‟output indicando la periferica su cui


inviarlo, il puntatore alla struttura MIDIHDR per la preparazione del buffer ed
infine la dimensione in byte di quest‟ ultima.

midiOutLongMsg(device , (LPMIDIHDR) pHeader, sizeof(MIDIHDR));

La funzione è quella che permette l‟ invio del messaggio e deve essere preceduta
obbligatoriamente dalla midOutPrepareHeader da cui riprende la stessa
tipologia di parametri.

midiOutUnprepareHeader(device , (LPMIDIHDR) pHeader, sizeof(MIDIHDR));

Quest‟ ultima elimina i dati creati dalla _PrepareHeader.

midiOutClose(device);

Eseguito l‟ invio del messaggio si realizza la chiusura della periferica midi di


connessione.
L‟ evento che opera la chiamata del metodo MakeSysex è il click sul pulsante per
l‟ invio delle modifiche apportate alla voce :

Figura 5.4 – Pulsante SEND SYSEX che consente la formattazione e l‟ invio del
messaggio midi (exclusive system message) contenenti le varie modifiche nella voce
interessata.

void CEditParDlg::OnOK()
{
MakeSysex2 (&g_dati_RAM[timbre][coupled][voice].Sysexcode , 2);

unsigned char * p;
char *p_temp;
p_temp = &g_dati_RAM[timbre][coupled][voice].NomeVoce[0];
p = (unsigned char*) p_temp;
MakeSysex(p , 17);

MakeSysex(&g_dati_RAM[timbre][coupled][voice].orgPart_exist , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].cc32 , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].cc0, 1);

68
Capitolo 5
27 novembre 2008

MakeSysex(&g_dati_RAM[timbre][coupled][voice].pc , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].volume , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].filter , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].micro_panpot , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].Panpot , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].voiceFamily , 1);

p_temp = &g_dati_RAM[timbre][coupled][voice].PoliphonicPriority;
p = (unsigned char*) p_temp;
MakeSysex(p , 1);

MakeSysex(&g_dati_RAM[timbre][coupled][voice].Env_Attack , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].Env_Decay , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].Env_Release , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].Env_Delay , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].RndTune_Probability , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].RndTune_MaxCents , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].pitch , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].pipe , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].outch , 1);
MakeSysex(&g_dati_RAM[timbre][coupled][voice].Dummy2[0] , 7);

p_temp = &g_dati_RAM[timbre][coupled][voice].Shor tNomeVoce[0];


p = (unsigned char*) p_temp;
MakeSysex(p , 9);

CDialog::OnOK();
}

La funzione membro relativa al bottone richiama la MakeSysex per ogni singolo


parametro indipendentemente da quali sono stati effettivamente modificati o
meno.
Ad ogni chiamata viene passato l‟ indirizzo del parametro e la sua dimensione. Da
notare come per i parametri NomeVoce, PoliphonicPriority, ShortNomeVoce sia
stato necessario implementare l‟ operazione di casting essendo di tipo iniziale
char.
Da sottolineare anche il fatto che esiste anche un funzione definita MakeSysex2
utilizzata esclusivamente per il sysexcode. Quest‟ ultimo parametro infatti risulta
l‟ unico ad assumere valori superiori a 127 quindi risulta necessario l‟ utilizzo di
2 byte (invece di 1). Tale metodo è identico alla MakeSysex originale e di seguito
viene riportata l‟ unica parte di codice diversa necessarria per lo split del suo
valore su 2 nibble (considerando di nuovo l‟ aspetto Big-endian Little-endian):

#ifdef INTEL_TYPE
midi_array[14] = (*p_value & 0x0F) ;
midi_array[13] = ((*p_value & 0xF0) >> 4);
#else

69
Capitolo 5
27 novembre 2008

midi_array[13] = (*p_value & 0x0F) ;


midi_array[14] = ((*p_value & 0xF0) >> 4);
#endif

5.3.4 – ELEMENTI GRAFICI

Il caricamento della bitmap di background e l‟ elaborazione dell‟ aspetto grafico


generale riutilizza il metodo ::ONPAINT e la proprietà OnDraw già illustrate e
specificate nella Dialog principale. Anche per tutte le altre Dialog del progetto per
quanto riguarda l‟ immagine di background il codice relativo per il suo
caricamento risulta essere sempre lo stesso, mentre si evidenzieranno
caratteristiche diverse di costruzione grafica deò dispositivo di interfaccia di tipo
“lista di bottoni” relativamente all‟ ultima dialog che verrà presentata nel
paragrafo 5.6 .

70
Capitolo 5
27 novembre 2008

5.4 – DIALOG EDIT PARAMETRI NOTA: IDD_DIALOG_NOTA

Figura 5.5 – Composizione strutturale della dialog per la modifica di 3 parametri multi
valore. La tastiera virtuale consente una visione globale dei 3 parametri consentendo
un‟ interazione agevolata rispetto all‟accesso nello strumento reale.

In tale Dialog l‟ utente può effettuare l‟ editing di 3 parametri ralativi ad ogni


singola nota corripondente alla voce selezionata nella dialog principale per mezzo
dei 3 solti indici della matrice g_dati_Ram[][][], cliccando sul tasto
corrispondente nella virtual keyboard. La “costruzione” di tale finestra utente è
implementata nei file EditParNotaDlg.cpp e EditParNotaDlg.h. Il nome della
nota in editing viene opportunamente visualizzato nella casella a sinistra della
tastiera virtuale ed i 3 parametri Volume , Tone, Pitch vengono valorizzati
numericamente nei rispettivi editbox.

La costruzione della virtual keyboard è stata possibile operando una opportuna


disposizione di elementi reattivi (pulsanti) nella dialog osservabile nel graphic
editor del Visual C++ e illustrata dalla seguente immagine.

71
Capitolo 5
27 novembre 2008

Figura 5.6 - Virtual keyboard (tastiera virtuale) la cui implemnetazione è stata


possibileoperando una opportuna disposizione di elementi reattivi (pulsanti) di tipo
CBitmapButton che consentano un caricamento dinamico di immagini sulla proprio
superficie.

Nel file header relativo alla dialog corrente è possibile visionare la definizione di
tutti i 128 pulsanti nel seguente modo:

CBitmapButton m_cNOTA0;


CBitmapButton m_cNOTA127;

Anche in questo caso ogni bottone è stato identificato con un opportuno ID a cui
risulta associato, con il ClassWizard, successivamente, il tipo di messaggio
ON_BN_CLICKED secondo la seguente mappatura:

ON_BN_CLICKED(IDC_NOTA0, OnNota0)


ON_BN_CLICKED(IDC_NOTA0, OnNota127)

In questo modo il click sulle note richiama il metodo relativo OnNota0 …


OnNota127. E‟ evidente che sia possibile l‟ editing di una singola nota per ogni
invio. Di seguito il codice della funzione membro corrispondente alla nota0.

void CEditParNotaDlg::OnNota0()
{
m_cEdVolumeNbn.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].volume_nbn[0]));
m_cEdToneNbn.For mat("% ld",_T(g_dati_RAM[timbre][coupled][voice].tone_nbn[0]));
m_cEdPitchNbn.Format("% ld",_T(g_dati_RAM[timbre][coupled][voice].pitch_nbn[0]));

72
Capitolo 5
27 novembre 2008

Il click sulla nota0 per prima cosa opera la formattazione dei valori nelle 3
variabili membro delle rispettive editbox impostando, logicamente, come indice
dei 3 vettori volume_nbn[], tone_nbn[] e pitch_nbn[] il numero 0.
p_volume = &g_dati_RAM[timbre][coupled][voice].volume_nbn[0];
p_tone = &g_dati_RAM[timbre][coupled][voice].tone_nbn[0];
p_pitch = &g_dati_RAM[timbre][coupled][voice].pitch_nbn[0];

Successivamente risultano definiti i 3 puntatori ai rispettivi valori dei e parametri


principali in editing necessari per la loro manipolazione.

m_cEdSelezioneNota.For mat("> C0 <");

Il nome della nota selezionata viene visualizzata nella rispettiva casella di testo
dell‟ interfaccia grafica.

m_cButtonVolumeNbn.EnableWindow(TRUE);
m_cButtonToneNbn.EnableWindow(TRUE;
m_cButtonPitchNbn.EnableWindow(TRUE);

All‟apertura della dialog corrente non risulta selezionata alcuna nota e di


conseguenza vengono disabilitati i 3 pulsanti di edit. Al successivo click nella
tastiera virtuale vi è la conseguente abilitazione tramite l‟ apposita funzione
EnableWindow.

UpdateData(FALSE);
}

La modifica dei 3 parametri avviene tramite altrettanti pulsanti di EDIT


identici a quelli già analizzati nella precedente dialog a cui corrispondono le
seguenti variabili membro:

CButton m_cButtonPitchNbn;
CButton m_cButtonToneNbn;
CButton m_cButtonVolumeNbn;

che utilizzano i seguenti metodi:

ON_BN_CLICKED(IDC_BUTTON_VOLUME_NBN, OnButtonVolumeNbn)
ON_BN_CLICKED(IDC_BUTTON_TONE_NBN, OnButtonToneNbn)
ON_BN_CLICKED(IDC_BUTTON_PITCH_NBN, OnButtonPitchNbn)

73
Capitolo 5
27 novembre 2008

caratterizzati dal codice:

void CEditParNotaDlg::OnButtonVolumeNbn()
{
CSLIDERDlg dlg;
min_range = 0;
max_range = 127;
p = p_volume;
if(dlg.DoModal() == ID_BUTTON_SLIDER_MODIFICA)
{
m_cEdVolumeNbn.For mat("% ld", *p);
UpdateData(FALSE);
}

return;
}

void CEditParNotaDlg:: OnButtonToneNbn()


{

p = p_tone;

}

void CEditParNotaDlg:: OnButtonPitchNbn()


{

p = p_pitch;

}

Si evidenzia il fatto che le varie funzioni membro risultano identiche a quelle già
illustrate per i pulsanti di EDIT presenti nella Dialog dei parametri generali
(Parametri Voce); l‟ unica differenza sta nell‟ assegnazione dei 3 puntatori
temporanei (p_volume, p_tone, p_pitch) a p in base al tipo di parametro che si
indende modificare.

5.4.1 – PULSANTE SEND SYSEX

Tale pulsante permette l‟ impiego della stessa MakeSysex già utilizzata in


precedenza e l‟ evento di click è gestito dalla seguente funzione membro:

void CEditParNotaDlg::OnButtonInviaModifiche()
{
MakeSysex (&g_dati_RAM[timbre][coupled][voice].volume_nbn[0] , 127);
MakeSysex (&g_dati_RAM[timbre][coupled][voice]. tone_nbn[0] , 127);
MakeSysex (&g_dati_RAM[timbre][coupled][voice].pitch_nbn[0] , 127);

74
Capitolo 5
27 novembre 2008

EndDialog(ID_BUTTON_INVIA_MODIFICHE);
}

Indipendentemente di valori modificati si verifica l‟ invio completo dei 3 vettori


relativi alla voce selezionata; il metodo makesysex è richiamato per ognuno dei 3
parametri, memorizzando nel messaggio esclusivo tutti i 127 valori caratterizzanti
le note della virtual keyboard. Infine il click del pulsante SEND_SYSEX chiude
la dialog corrente.

5.4.2 – ELEMENTI GRAFICI

L‟ immagine di background si dimostra caricata tramite il metodo OnPaint() le


cui funzionalità sono state illustrate recentemente.
Per quanto riguarda, invece, il caricamento di bitmap sulla superficie dei
pulsanti per la creazione e il funzionamento della virtual keyboard, si è sfruttata
la proprietà Owner Draw e i messaggi per gli eventi del mouse definiti dai metodi
di Windows: WM_LBUTTONDOWN e WM_LBUTTONUP.
Come già evidenziato in altre circostanze, anche in tale contesto la variab ile di
controllo associata ad ogni pulsante (m_cNOTAx) richiama il metodo.
LoadBitmaps(); il caricamento delle bitmap, in tale caso, risulta diversificato
distinguendo la parte di tasti bianchi e la restante parte di tasti neri, come si può
evincere dal seguente codice implementato all‟ intero della OnInitDialog():

//Caricamento bitmaps TASTI BIANCHI

m_cNOTA0.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, ID B_DISABLE);


m_cNOTA2.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, ID B_DISABL E);
m_cNOTA4.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, ID B_DISABLE);
m_cNOTA5.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, ID B_DISABLE);
m_cNOTA7.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, ID B_DISABLE);
m_cNOTA9.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, ID B_DISABLE);
m_cNOTA11.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA12.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA14.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA16.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA17.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA19.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA21.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA23.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA24.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA26.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA28.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);

75
Capitolo 5
27 novembre 2008

m_cNOTA29.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);


m_cNOTA31.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA33.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA35.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA36.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA38.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA40.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA41.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA43.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA45.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA47.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA48.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA50.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA52.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA53.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA55.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA57.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , ID B_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA59.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA60.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA62.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA64.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA65.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA67.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISA BLE);
m_cNOTA69.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA71.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA72.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA74.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA76.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA77.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA79.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA81.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA83.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA84.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA86.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA88.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA89.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DO WN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA91.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA93.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA95.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA96.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA98.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA100.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA101.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA103.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA105.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA107.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA108.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA110.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA112.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA113.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA115.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA117.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA119.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA120.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA122.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA124.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA125.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);
m_cNOTA127.LoadBitmaps(IDB_NOTA_UP, IDB_NOTA_DOWN , IDB_NOTA_FOCUS, IDB_DISABLE);

76
Capitolo 5
27 novembre 2008

Le 4 immagini caricate tramite il loro ID sono:

IDB_NOTA_ IDB_NOTA_ IDB_NOTA_ IDB_


UP DOWN FOCUS DISABLE

(bianco)
(bianco)

Tasto rilasciato
Tasto Tasto in fase di Tasto
(effettuata la
non cliccato click (schiacciato) disabilitato
selezione)
Figura 5.7 - Caricamento di bitmap sulla superficie dei pulsanti relativi ai tasti bianchi
per la creazione e il funzionamento della virtual keyboard, sfruttando la proprietà
Owner Draw

//Caricamento bitmaps TASTI NERI

m_cNOTA1.LoadBitmaps(IDB_NOTA_BLACK_UP, IDB_NOTA_BLACK_DOWN , IDB_NOTA_FOCUS,


IDB_NOTA_BLACK_DISABLE);


m_cNOTA126.LoadBitmaps(IDB_NOTA_BLACK_UP, IDB_NOTA_BLACK_DOWN , IDB_NOTA_FOCUS,
IDB_NOTA_BLACK_DISABLE);

Ora le 4 immagini caricate tramite il loro ID sono:

IDB_NOTA_ IDB_NOTA_ IDB_NOTA_ IDB_NOTA_


BLACK_UP BLACK_DOWN FOCUS BLACK_DISABLE

Tasto rilasciato
Tasto Tasto in fase di Tasto
(effettuata la
non cliccato click (schiacciato) disabilitato
selezione)
Figura 5.8 - Caricamento di bitmap sulla superficie dei pulsanti relativi ai tasti neri per
la creazione e il funzionamento della virtual keyboard, sfruttando la proprietà Owner
Draw

77
Capitolo 5
27 novembre 2008

Lo stesso metodo è utilizzato per il caricamento del bottone SEND_SYSEX :

m_cSendSysex.LoadBitmaps(IDB_SEND_UP, IDB_SEND_DOWN , IDB_DISABLE, IDB_DISABLE);

5.5 – DIALOG SLIDER: IDD_DIALOG_SLIDER

La modifica del valore numerico dei vari parametri ralativi alla voce selezionata
nella dialog principale, avviene attraverso il click sull‟ apposito pulsante
>EDITA< che opera l‟ apertura di una nuova finestra qui visualizzata:

Figura 5.9 – Dialog per la modifica del valore relativo al parametro in editing. L‟
elemento di tipo reattivo implementato è un cursore scorribile orizzontalmente definot
come Slider.

L‟ elemento principale della dialog risulta essere il cursore in alto che l‟ utente
può muovere orizzontalmente tramite il mouse. Si tratta di un nuovo oggetto
implementabile direttamente dal developer studio definito come slide r. Ai suoi
estremi sono sistemate 2 editbox (non modificabili dall‟ utente) cui vengono
fissatti i range massimo e minimo del parametro corrente in editing. Ciò
garantisce anche un„ ottima tolleranza verso gli errori dell‟ utente evitando l‟
inserimento di valori non validi. Nella parte centrale vi è posizionato un altro
editbox per la visualizzazione del valore attuale del parametro che risulta
aggiornato opportunamente ad ogni spostamento del cursore interno allo slider.
Per rendere effettiva la modifica apportata al valore, l‟ utente deve cliccare sul

78
Capitolo 5
27 novembre 2008

pulsante in basso. In tale modo viene aggiornato sia il valore del campo
corrispondente al parametro nella struttura voci in RAM, sia la quantità
visualizzata nella dialog di origine. Il funzionamento dettagliato di quanto
illustrato risulta definito nei file di progetto SLIDERDlg.cpp e .h .

5.5.1 –SPECIFICHE DI FUNZIONAMENTO

Importante la definizione delle seguenti variabili globali:

extern int min_range, max_range;


extern unsigned char *p;

tramite cui, dalla finestra “madre”, la chiamata della SLIDERDlg consente di


fissare il puntatore al parametro da modificare e il range di valori massimo e
minimo ammissibili.

BOOL C SLIDERDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_cEdSlider1.SetRangeMin(("% d", min_range), false);
m_cEdSlider1.SetRangeMax(("% d", max_range), false);
m_cEdSliderValue.For mat("% ld", *p);
m_cEdMinRange.For mat("% ld", min_range);
m_cEdMaxRange.For mat("% ld", max_range);

m_cButtonSlider.LoadBitmaps(IDB_SLIDER_UP, IDB_SLIDER_DOWN ,
IDB_SLIDER_UP, ID B_DISABLE);

}

Nell„ inizializzazione della dialog si assegnano i valori di massimo e minimo sia


alla variabile membro dello slider, tramite le funzioni SetRangeMin e
SetRangeMax, sia alle variabili membro delle editbox situate agli estremi dello
slider. Inoltre viene inizializzata al valore corrente, letto da RAM tramite il
puntatore globale p, la casella di testo centrale identificata tramite l‟ apposita
variabile m_cEdSliderValue.
Infine, sfruttando la già nota proprietà Owner Draw dei pulsanti, il metodo
LodBitmaps() permette il corretto caricamento delle immagini sul pulsante
“Conferma Modifica”.
79
Capitolo 5
27 novembre 2008

La funzione membro interna alla dialog che gestisce le funzionalità dello slider è
la seguente:

void CSLIDERDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)


{

if(nSBCode == SB_THUMBPOSITION) {
m_cEdSliderValue.For mat("% ld", nPos);
slider_value = 0;
slider_value = nPos;
UpdateData( false);
}

else {
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

CDialog::OnHScroll(nSBCode, nPos, pScrollBar);


}

Essa coordina lo spostamento del cursore aggiornando il valore visualizzato nella


casella sottostante, assegnandolo alla variabile globale slider_value.

80
Capitolo 5
27 novembre 2008

5.6 – DIALOG: IDD_SELEZIONE_VOCI_MULTIPLE

La funzionalità di tale dialog si distacca dal progetto centrale che si è basato


sull‟ editing di tutti i parametri relativi ad una singola voce selezionata dall‟
utente. In questa nuova finestra si è voluto creare un elenco di tutte le voci
presenti all’ inte rno dello strume nto elettronico Rodgers i538 per operarne
sostanzialmente una selezione multipla senza alcuna operazione di editing.
Ovvero si è reputato necessario avere a disposizione uno strumento grafico che
permetta all‟ utente di attivare o disattivare da una fino a 245 voci di registro
contemporaneamente e indistintamente dall‟ ordine di selezione.
L‟ apertura di tale dialog è possibile tramite il pulsante

Figura 5.10 – Pulsante di inizializzazione ed apertura della finestra di dialogo con


funzionalità di multi selezione timbrica delle 245 voci di registro.

presente nell‟ interfaccia principale il cui click richiama il seguente metodo:

void CRODGERS_i385_GUIDlg:: OnMenuSelezioneVociMultiple()


{

CSelezioneVociMultipleDlg dlg;
int i =0;
int sum ,ck ,w ;
ck = 0;

midi_voci[0] = 0xF0;
midi_voci[1] = 0x41;
midi_voci[2] = 0x10;
midi_voci[3] = 0x30;
midi_voci[4] = 0x12;
midi_voci[5] = 0x01;
midi_voci[6] = 0x00;
midi_voci[7] = 0x00;
midi_voci[8] = 0x00;
midi_voci[9] = 0x00;
midi_voci[10] = 0x00;
midi_voci[11] = 0x00;
midi_voci[12] = 0x00;
midi_voci[13] = 0x00;
midi_voci[14] = 0x00;
midi_voci[15] = 0x00;
midi_voci[16] = 0x00;
midi_voci[17] = 0x00;
midi_voci[18] = 0x00;

81
Capitolo 5
27 novembre 2008

midi_voci[19] = 0x00;
midi_voci[20] = 0x00;
midi_voci[21] = 0x00;
midi_voci[22] = 0x00;
midi_voci[23] = 0x00;
midi_voci[24] = 0x00;
midi_voci[25] = 0x00;
midi_voci[26] = 0x00;
midi_voci[27] = 0x00;
midi_voci[28] = 0x00;
midi_voci[29] = 0x00;
midi_voci[30] = 0x00;
midi_voci[31] = 0x00;
midi_voci[32] = 0x00;
midi_voci[33] = 0x00;
midi_voci[34] = 0x00;
midi_voci[35] = 0x00;
midi_voci[36] = 0x00;
midi_voci[37] = 0x00;
midi_voci[38] = 0x00;
midi_voci[39] = 0x00;
midi_voci[40] = 0x00;
midi_voci[41] = 0x00;
// Calcolo del Checksum
sum = 0;
for (w=7 ; w <=41 ; w++)
{
sum += midi_voci[w] ;
}
sum &= 0x7F;
ck = (128 - sum)&0x7F;

midi_voci[42] = ck;
midi_voci[43] = 0xF7;

dlg.DoModal();
return;
}

Praticamente tale metodo inizializza il midi_voci[43] definito globalmente come


un array di elementi unsigned char. Dall‟ Appendice D è possibile visionare l‟
intero elenco delle 245 voci presenti all‟ interno dello strumento. Come è
possibile notare, ogni singolo nome_voce è associato al bit (da 0 a 6) di un certo
byte. L‟ attivazione delle voci può essere configurata su 35 byte totali. Ad
esempio, se si volesse selezionare la voce 1 (16‟ Principal) bisognerebbe mandare
un messaggio esclusivo in cui settare ad 1 il bit 1 del byte 0 e lasciare a 0 i restanti
byte. Per tale scopo è stato creato l‟ array midi_voci[43] dove effettivamente i
primi 6 elementi identificano la codifica del messagio esclusivo, me ntre nei
successivi (tranne gli ultimi 2 byte utilizzati dal checksum e dall‟ F7) si

82
Capitolo 5
27 novembre 2008

dispongono i byte relativi all‟ attivazione delle voci corrispondenti. Quindi, al


momento in cui l‟ utente interagisce sul pulsante di apertura della dialog,
automaticamente viene inizializzato in RAM un array dove, dall‟ elemento 6 all’
elemento 41, il valore risulta settato a 0x00 che corrisponde ad una logica
inizializzazione con tutte le voci spente (maggiori specifiche sono visibili nel par.
6.2 al 3° esempio).

5.6.1 – SPECIFICHE_1: LISTA DI BOTTONI

Figura 5.11 – Dialog presentante il dispositivo di interfaccia: Lista di Bottoni. E‟ data la


possibilità di multi-selezione timbrica sfruttando elementi d‟ interfaccia di tipo reattivo
contraddistinguenti le voci attivate con un led rosso accesso.

83
Capitolo 5
27 novembre 2008

Nella lista ad ogni bottone corrisponde una voce; le voci selezionate hanno il
rispettivo led acceso (rosso) mentre le altre risultano spente.
I file di progetto per la costruzione e il funzionamento di questo dispositivo d‟
interfaccia sono: SelezioneVociMultipleDlg.cpp, LedButton.cpp, Led.cpp,
ButtonListBox.cpp e i rispettivi file header.
La creazione di ogni singolo bottone della lista è difinita dalla seguente classe
dichiarata nel file LedButton.h :

class CLedButton : public C Button


{
// Construction
public:
CLed* GetLed() {return
………….&m_Led;}
void SetTextColour(COLORREF TxtColour) {m_TextColour =
………….TxtColour;}
void SetButtonColour(COLORREF ButtonColour) {m_ButtonColour =
………….ButtonColour;}
CWnd* GetParent()
{return m_pParent;}
void CentreLED();
CLedButton(CString ButtonText,long Bu ttonId,C Wnd* Parent);
CString GetButtonText() {return
………….m_ButtonText;}
long GetButtonId() {return m_ButtonId;}

// Attr ibutes
private:
CRect m_LEDLocation;
COLORREF m_TextColour;
COLORREF m_ButtonColour;
CWnd* m_pParent;
CString m_ButtonText;
long m_ButtonId;

public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CLedButton();

// Generated message map functions


protected:
//{{AFX_MSG(CLedButton)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnClicked();
//}}AFX_MSG

84
Capitolo 5
27 novembre 2008

CLed m_Led;
BOOL CreateLED();

DECLARE_MESSAGE_MAP()
};

La creazione di una nuova istanza all‟ interno della lista bottoni è data dal metodo

void CButtonListBox::AddItem(LPCTSTR ButtonTex t,long idButton)


{

CLedButton* pAddedButton;
static int count = 0;
CRect rect;
CRect ButtonRect;

count++;
GetClientRect( rect );

pAddedButton = new CLedButton(ButtonText,idButton,this);


ButtonRect.SetRect( 0, 0, rect.Width(), (rect.Height() /
NUMBER_OF_BUTTONS_IN_LIST_VIEW) );
pAddedButton->Create( "", WS_CHILD|BS_OWNERDRAW, ButtonRect, this,
1001+count );

Si verifica quindi la generazione di un nuovo bottone, identificabile tramite il


nome della voce, a cui risulta assegnato un idButton progressivo, in seguito
necessario per l‟ accensione o lo spegnimento della voce stessa.
La creazione dell‟ intera lista risulta operata all‟ interno della funzione di
inizializzazione della dialog come si può evincere dal codice seguente (l „intero
codice è visionabile nell‟ Appendice C_1):

BOOL C SelezioneVociMultipleDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_curr_indice=0;
InsertVoce("unused");
InsertVoce("16'Principal");
InsertVoce("16'Flute");
InsertVoce("8'Principal");


InsertVoce("_spare_");
InsertVoce("Test/Tune Mode");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");

85
Capitolo 5
27 novembre 2008

Rispettando l‟ elenco originale Roland di successione delle voci, viene richiamata


per 245 volte la funzione membro InsertVoce() che riceve come parametro la
stringa da assegnare alla nuova istanza della ButtonListBox.

void CSelezioneVociMultipleDlg::Inser tVoce(LPCSTR name)


{
m_ButtonListBox.AddItem(name,m_curr_indice);
m_curr_indice++;
}

Tale metodo effettivamente richiama la funzione di creazione della lista già


illustrata precedentemente (AddItem) , a cui passa come parametri la stringa e l‟
indice corrente incrementato ad ogni iterazione. Tale prerogativa fa sì che ad ogni
bottone corrisponda lo stesso numero di voce progressivo della lista voci originale
Roland, permettendone una univoca e precisa individuazione. Ciò è necessario per
la corretta gestione dei messaggi di spegnimento e accensione contemporanei di
più voci da parte dell‟ interfaccia grafica e del sistema operativo.

5.6.2 – SPECIFICHE_2: MODALITA’ DI FUNZIONAMENTO

Nella programmazione win32 ad ogni applicazione risulta associata un


veicolazione dei massaggi tramite un canale con cui ogni oggetto della finestra
comunica con la applicazione principale. In pratica tutti gli eventi (pressione di un
tasto,movimento del mouse ecc) generano un messaggio che viene inserito in
questo canale dal quale il sistema lo preleva e lo consegna (dispatch)
all'applicazione associata. Su questo schema si basa il funzionamento della lista di
bottoni implementata nel progetto in analisi.
Il click di un singolo bottone è gestito dal seguente metodo:

void CLedButton::OnClicked()
{
HWND ParentHwnd = m_pParent->m_hWnd;

::PostMessage(ParentHwnd,UM_BUTTON_CLICK,0,(DWORD)this);
}

86
Capitolo 5
27 novembre 2008

Importante nella funzione è il metodo di windows ::PostMessage() l‟ invio di


messaggi in quel canale di comunicazione con la finestra principale di cui si è
parlato recentemente. Il click su uno qualsiasi dei 245 bottoni invia alla finestra
windows attuale il preciso messaggio UM_BUTTON_CLICK , ovvero avverte l‟
applicazione che è stato pigiato un pulsante della lista.
Ora il sistema operativo deve operare una interpretazione di questo messaggio
inviatogli per rimandarlo in modo opportuno all‟ applicazione principale.
E‟ ciò che viene effettivamente fatto dal metodo PreTranslateMessage(MSG*
pMsg) come dimostra il seguente codice:

BOOL C ButtonListBox::PreTranslateMessage(MSG* pMsg)


{
CLedButton* pButton = NULL;
CWnd* Parent = NULL;
Parent = GetParent();
if(pMsg->message == UM_BUTTON_CLICK)
{
pButton = (CLedButton*)pMsg->lParam;
if(pButton->GetLed()->GetLedMode() == CLed::LED_ON)
{
pButton->GetLed()->SetLed
(CLed::LED_COLOR_YELLOW,CLed::LED_OFF,CLed::LED_ROUND);
}
else
{
pButton->GetLed()->SetLed
(CLed::LED_COLOR_RED,CLed::LED_ON,CLed::LED_ROUND);
}

Tale metodo riceve il messaggio dalla PostMessage() precedentemente illustrata.


Se tale mesaggio risulta proprio uguale a UM_BUTTON_CLICK effettua un
secondo controllo. Verifica se il led del pulsante cliccato risulta acceso; nel primo
caso vuol dire che è stato selezionata una voce già accesa e quindi con il nuovo
click si deve effettuarne il suo spegnimento. Nel caso in cui non sia già accesa
bisogna effettivamente attivarla (accensione led).

acceso = false;
acceso = pButton->GetLed()->GetLedMode()==CLed::LED_ON;
CString sel = pButton->GetButtonText();
long idSel = pButton->GetButtonId();

if(Parent)
{
::PostMessage(Parent->
m_hWnd,WM_SEND_PARAM,idSel,(DWORD) this);

87
Capitolo 5
27 novembre 2008

}
}

return CListBox::PreTranslateMessage(pMsg);
}

Nella parte finale importante è l‟ assegnazione del valore dell‟ ID, relativo al
bottone selezionato tramite il metodo della classe CButton definito GetButtonId(),
alla variabile idSel. Successivamente viene richimata la funzione membro di
windows PostMessage() di cui verranno approfondite le sue specifiche.
Il suo costrutto base è dato da:

BOOL PostMessage(

HWND hWnd,
UINT Msg,
WPARAM w Param,
LPARAM lParam

);

Invia un messagio alla finestra dell‟ applicazione corrente. Il messaggio (Msg) in


tal caso risulta essere WM_SEND_PARAM; la sua definizione è stata effettuata
nel file header Global.h :

#define WM_SEND_PA RAM WM_USER+2100

è stato utilizzata la WM_USER+2100 per distinguerlo dai vari messaggi


predefiniti di windows. Inoltre risulta presente anche un messaggio supplementare
come terzo parametro di trasmissione (wParam) corrispondente all‟ idSel.
Riassumendo questa procedura invia alla finestra di windows un messaggio in cui
indica l‟ evento di click di un bottone della lista col relativo id corrispondete al
nome della voce selezionata.
Ora, per mezzo della

ON_MESSAGE( WM_SEND_PARAM, OnSendParam )

l‟ appliazione rileva l‟ evento di click di un bottone e attiva la funzione membro


che consente la costruzione effettiva del messaggio esclusivo midi_voci[43]
settando ad 1 il bit (nel byte) della voce selezionata.

88
Capitolo 5
27 novembre 2008

LRESULT CSelezioneVociMultip leDlg::OnSendParam(WPARAM wParam,


LPARAM lParam)
{
long idSel=wParam;
int param_1,param_ 2;
unsigned char param_3;

param_ 1 = (idSel/7) + 7;
param_ 2 = idSel%7;
param_ 3 = 0;

switch(param_2) {

case 0: // Bit 0 settato a 1


param_ 3 = 0x01;
break;

case 1: // Bit 1 settato a 1


param_ 3 = 0x02;
break;

case 2: // Bit 2 settato a 1


param_ 3 = 0x04;
break;

case 3: // Bit 3 settato a 1


param_ 3 = 0x08;
break;

case 4: // Bit 4 settato a 1


param_ 3 = 0x10;
break;

case 5: // Bit 5 settato a 1


param_ 3 = 0x20;
break;

case 6: // Bit 6 settato a 1


param_ 3 = 0x40;
break;

Tale metodo riceve come parametro l‟ id del bottone cliccato e lo assegna alla
variabile locale idSel. Effettua poi il calcolo dei parametri 1 e 2. Sfruttando il
fatto che le voci risultano disposte in gruppi di 7 (ogni gruppo identifica 1 byte),
si possono calcolare facilmente il byte e il bit corrispondenti alla voce selezionata.
Il param_1 indica il numero del byte a cui appartiene la voce e viene calcolato con
una semplice divisione incrementato poi di 7 in quanto i primi 6 elementi dell‟
array sono occupati dall codifica del messaggio esclusivo. Il param_2 indica il
numero del bit da settare ad 1, ed è ottenuto come resto della divisione precedente.

89
Capitolo 5
27 novembre 2008

Il successivo costrutto switch(param_2) permette la converione in esadecimale


(param_3) del bit calcolato come resto della divisione.
if(acceso)
{
midi_voci[param_1] = midi_voci[param_ 1] | param_ 3;
Tramite il settaggio della variabile bool globale si memorizza il byte relativo alla
voce corrente. Se la voce deve essere attivata (acceso = vero) avviene il settaggio
del bit corrisondente utilizzando l‟ operazione di OR col byte corrispondente in
modo di lasciare a 0 (o ad 1) gli altri bit già eventualmente impostati.
}
else
{
midi_voci[param_1] = midi_voci[param_1] - param_3
}
Se la voce, invece, deve essere disattivata (acceso = false) viene effettuata l‟
operazione di sottrazione col numero di bit corrispondete in esadecimale.
SendSysex();
A questo punto si richiama il metodo SendSysex() per la formattazione del
messaggio midi e l‟ apertura del device di output midi, le cui funzionalità sono
state ampiamente descritte precedentemente.
Il codice implementativo relativi allo sviluppo di quest‟ ultmima finestra di
dialogo dell‟ applicativo compare integralmente nell‟ Appendice C_2.

90
Capitolo 6
27 novembre 2008

6. - VERIFICA FUNZIONAMENTO DEL’ INTERFACCIA

6.1 – UTILIZZO DI UN MIDI-MONITOR

L‟ ingegnerizzazione della Graphic User Interface finale si è avvalsa dell‟ utilizzo


di apposite strumentazioni software ed hardware di analisi e supporto dello
applicativo nelle varie fasi di sviluppo progettuale. Una di esse è sicuramente il
midi-monitor uno strumento di anali dei dati midi in grado di visualizzare la
sequenze di byte costitutivi di un sistema esclusivo o di un messaggio di canale.
Esistono midi- monitor sia hardaware che software entrambi dotati di schermo o di
un‟ interfaccia visiva e di una o più porte di I/O midi. La visualizzazione degli
eventi può essere selettiva operando un filtraggio dei dati in entrata o in uscita
identificando chiaramente le sequenze di eventi midi tramite l‟ assegnazione di un
codice identificativo della categoria a cui appartiene.…………………………

Lo sviluppo progettuale si è avvalso di entrambi le tipologie, ma per questioni di


praticità in tale breve sezione di verifica si prende in considerazione solo la
tipologia software facilmente “trasportabile” e accessibile in qualsiasi momento.
Nell‟ ambito applicativo considerato bisogna mettere in risalto il fatto che
l‟implementazione delle funzionalità midi dell‟ interfaccia rispetta pienamente le
specifiche GM e del costruttore Roland. Tuttavia l‟ organo liturgico Rodgers i538
non implementa ancora le parti software necessarie all’ interfacciament o con
questo nuovo applicativo; tale questione verrà trattata proprio nel prossimo ed
ultimo paragrafo concernente gli sviluppi futuri. Quindi si comprende subito quale
sia stato il ruolo del midi- monitor in tale contesto d‟ utilizzo garantendo un
supporto di verifica rapido ed affidabile.

Di seguito possiamo vedere un‟ esempio di midi-monitor software in quanto in


rete è possibile trovarne facilmente di vari tipi (si diversificano soprattutto per l‟
interfaccia utente), ma che racchiudono tutti le stesse funzioni di base.

91
Capitolo 6
27 novembre 2008

Figura 6.1 – Midi-Monitor software in grado di creare una connessione midi virtuale del
sistema operativo interfacciandosi (virtualmente) con l‟ applicativo d‟ interfaccia
sviluppato per la verifica dei messaggi midi inviati.

Il software crea una connessione midi virtuale all‟ interno del sistema operativo
in cui è installato (8 device di I/O denominati MIDI Yoke 1 – 8). Quindi
lanciando l‟ eseguibile dell‟ interfaccia grafica del Rodgers i538 nella combo box
relativa alla scelta del Device Midi da utilizzare per la comunicazione, si
seleziona il MidiDevice0 corrispondente al canale MIDI Yoke 1. Risulta quindi
possibile visualizzare i messaggi midi in “uscita” dall‟ interfaccia verificandone la
correttezza compositiva.

Quindi si effettuerà la dimostrazione della coerenza costruttiva dell‟ applicativo


d‟ interfaccia tramite 3 esempi essenziali.

6.2 – 3 ESEMPI ESSENZIALI

 Nel primo esempio si esegue la verifica del messaggio inviabile dalla prima
interfaccia di editing (PARAMETRI VOCE). Dopo aver selezionato una voce
principale semplicemente cliccando sul pulsante SEND SYSEX (senza effettuare
alcuna modifica ai 23 parametri visualizzati) la GUI invierà il messaggio midi
standardizzato (par. 5.3.3) sul canale di comunicazione indicato.

92
Capitolo 6
27 novembre 2008

Dal midi- monitor (già attivo) vengono immediatamente visualizzate le sequenze


di byte (esadecimale) ricevute evidenziando la loro composizione strutturale.

Figura 6.2 – Dal Midi-Monitor software risultano visualizzabili 23 blocchi consecutivi di


messaggi relativi ai rispettivi parametri della Dialog di editing dei parametri voce
(par.5.3)

Si possono individuare 23 blocchi di byte consecutivi rappresentanti ciascuno la


sequenza di implementazione midi utilizzata ed ampiamente illustrata (par 5.3.3)

93
Capitolo 6
27 novembre 2008

per la trasmissione dei 23 parametri modificabili. Ogni blocco ha dimensioni


diverse e presenta le caratteristiche salienti relative allo standard midi del
costruttore Roland analizzato nel paragrafo 3.6 . Ogni sequenza esibisce la
formattazione del messaggio esclusivo standard (fig . 4.2) riscontrabile dai
seguenti byte:
F0 41 10 30 12 06 _[DATI]_ CK F7
La lunghezza di ogni blocco è direttamente proporzionale al numero di valori
editabili e caratterizzanti il parametro considerato. Infatti dal 3° al 21° blocco si
evidenzia una stessa lunghezza delle sequenze; essi risultano legati ai rispettivi
parametri costituiti da un unico valore. I restanti blocchi 1, 2, 22 e 23 presentano
una strutturazione fondata su un numero di byte maggiore; ciò verifica l‟ effettiva
coerenza dell„ applicativo sviluppato avvalendosi della perfetta integrazione tra
potenzialità di sviluppo grafico ed interazione con le funzioni Win32 di
comunicazione ed interfacciamento midi.

 Nel secondo esempio si esegue la verifica del messaggio inviabile dalla


seconda interfaccia di editing (PARAMETRI NOTA).

Figura 6.2 – Dal Midi-Monitor software risultano visualizzabili 23 blocchi consecutivi di


messaggi relativi ai rispettivi parametri della Dialog di editing dei parametri voce
(par.5.3)

94
Capitolo 6
27 novembre 2008

Tale finestra di dialogo, come già visto, è caratterizzata dal particolare dispositivo
dì interazione grafica di tipo tastiera virtuale. Il messaggio esclusivo relativo ai
suoi 3 parametri editabili è esaminabile nell‟ interfaccia del midi- monitor in
Figura 6.2 . Le 3 sequenze mostrano una stessa lunghezza complessiva dei
messaggi esclusivi inviati dall‟ interfaccia; ciò riflette la prerogativa di
inserimento e formattazione dei blocchi midi conformemente alla natura dai
parametri rappresentati, che in questo caso hanno una strutturazione vettoriale
monodimensionale costituita di 128 elementi ciascuno.

Si riscontra quindi che il software implementato è perfettamente operativo ed


efficiente nell‟ osservanza dei protocolli di comunicazione sviluppati ed
ottimizzati per l‟ interazione diretta con l‟ hardware midi esterno. In particolare
risulta efficace la soluzione adottata per la composizione base di ogni system
exclusive message attuabile per mezzo di unico costrutto di programmazione
identificato nella funzione MakeSysex (par. 5.3.3).

Il messaggio midi inviato risulta impacchettato in un Array costruito


dinamicamente in relazione al numero di valori caratterizzanti quel particolare
parametro. La funzione MakeSysex ne effettua la standardizzazione con
l‟ inclusione dei byte di apertura e chiusura del messaggio (F0 – F7); nel corpo
del system exclusive message inserisce dinamicamente le sequenze di byte
relative ai valori editabili (1 byte = 1 valore)

95
Capitolo 6
27 novembre 2008

 Nel terzo ed ultimo esempio si esegue la verifica del messaggio inviabile dall‟
interfaccia di multi selezione timbrica nell‟ insieme delle voci strutturanti
l‟ organo Rodgers i538.

Figura 6.3 – Dal Midi-Monitor software risultano visualizzabili 23 blocchi consecutivi di


messaggi relativi ai rispettivi parametri della Dialog di editing dei parametri voce
(par.5.3)

Come già visto ampiamente nel precedente capitolo, la finestra di dialogo


consente all‟ utente di attivare o disattivare una o più voci contemporaneamente
(senza però effettuarne l‟ editing) . La situazione in cui le voci risultano tutte
spente è quella visionabile nel blocco 2 di Figura 6.3 dove tutti i byte della
sequenza riservati a tale funzione (dal byte numero 8) risultano settati a 0x00.

I blocchi in sequenza inoltre non sono contemporanei come nei due esempi
precedenti; ma risultano ottenuti in più interazioni consecutive con la lista di
bottoni eseguendo le seguenti operazioni:

 Block#1 - accensione voce numero 1 (16‟ Principal)


 Block#2 - spegnimento voce numero 1. Q uindi coincide con la
situazione in cui tutte le voci risultano disattivate.
 Block#3 – riaccensione voce numero 1
 Block#4 – accensione voce numero 2

96
Capitolo 6
27 novembre 2008

 Block#5 - accensione voce numero 3


 Block#6 - accensione voce numero 4
 Block#7 - accensione voce numero 5

Effettivamente ciò verifica quanto già visionato nelle modalità di funzionamento


espletate nel paragrafo 5.6; dall‟ Appendice D è possibile capire come ogni
singolo nome_voce sia associato al bit (da 0 a 6) di un certo byte. L‟ attivazione
delle voci può essere configurata su 35 byte totali. Per tale scopo è stato creato l‟
array midi_voci[43] dove effettivamente i primi 6 elementi identificano la
codifica del messagio esclusivo, mentre nei successivi (tranne gli ultimi 2 byte
utilizzati dal checksum e dall‟ F7) si dispongono i byte relativi all‟ attivazione
delle voci corrispondenti.

Nell‟ esempio quindi l‟ attivazione delle prime 5 voci effettua il cambiamento


solo del primo byte (7° elemento della sequenza) utile per l‟ inserimento delle
voci di registro dell‟ organo.

Da notare come in questo caso non vi sia una creazione dinamica del messaggio
esclusivo come avviene invece negli esempi precedenti. All‟ apertura di tale
finestra si inizializza un vettore di 44 elementi la cui lunghezza rimane costante
nell‟ intera fase di interazione con l‟ utente in quanto il numero di voci rimane
costante; varia sol il numero di quelle effettivamente attive.

97
Capitolo 7
27 novembre 2008

7. - SVILUPPI FUTURI E CONCLUSIONI

La complessa architettura della Graphic User Interface ingegnerizzata in


collaborazione col personale specializzato dell‟ azienda Roland mette alla luce
una perfetta integrazione tra funzionalità grafiche ottimizzate, stile di interazione
diversificato ed ottima implementazione delle funzionalità midi standardizzate
permettendo il raggiungimento degli obbiettivi basilari di questa tesi sperimentale.
Le potenzialità dell‟ applicato sviluppato mettono alla luce anche le sue
prospettive di crescita ed evoluzione future incentrando l‟ attenzione:

 sulle modalità di implementazione software da sviluppare e collaudare


all‟ interno dello strumento musicale elettronico reale;
 sull‟ ampliamento delle funzionalità d‟ interfaccia includendo anche il
supporto di tutte e 4 le configurazioni delle voci di registro costituenti il
RODGERs i538;
 sui miglioramenti apportabili nell‟ interfacciamento con l „intera gamma
di strumenti musicali della famiglia RODGERs (organi liturgici).

 Si è potuto constatare dal capitolo precedente come il funzionamento generale


della Graphic User Interface non sia stato collaudato in interazione diretta con
l‟ organo liturgico reale. La verifica di coerenza dei dati midi inviati dall‟
applicativo, infatti , si è avvalsa del supporto di midi- monitor (software ed
hardware) consentendo un riscontro grafico dei vari messaggi esclusivi transitanti
nel canale (midi) di comunicazione preso in esame.
Appare quindi la necessità di creare l‟ archetipo delle strutture software da
implementare e collegare adeguatamente all‟ interno dello strumento fisico reale.
Il Rodgers i538 deve essere in grado di poter interpretare correttamente le varie
sequenze di messaggi esclusivi che entrano sulla porta di midi input.
Presumibilmente si dovranno realizzare costrutti di programmazione software in
grado di effettuare un „operazione di “spacchettamento” per ogni blocco di
messaggi in ingresso individuando il tipo di parametri cui si riferiscono e il
numero di valori globali (editati) che li caratterizzano.

98
Capitolo 7
27 novembre 2008

E‟ possibile quindi effettuare un eventuale confronto generale tra le funzioni di


creazione del messaggio (nell‟ interfaccia) e quelle di “lettura” nello strumento
musicale reale.

 Elenco delle funzionalità dell‟ interfaccia adibite all‟ invio dei messaggi
esclusivi garantendo anche l‟ apertura e il corretto utilizzo delle componenti API
del sistema:
 individuazione dei 3 indici di accesso alla voce desiderata

 accesso all‟ indirizzo di memoria del parametro (della voce) selezionato


dall‟ utente tramite appositivi dispositivi d‟ interfaccia
 lettura del valore o dei valori caratteristici del parametro editato

 costruzione dinamica del system exclusive message posizionando i valori


letti e l‟ indirizzo di memoria del parametro negli appositi byte
prestabiliti dallo standard di implementazione sviluppato

 invio multiplo dei messaggi (più sequenze di blocchi racchiusi dai byte
F0 – F7)

 Elenco delle funzionalità del software da implementare nell‟ organo


liturgico adibite ad una corretta ricezione ed interpretazione dei messaggi
esclusivi provenienti dall‟ interfaccia grafica esterna:

 ricezione multipla dei system exclusive message

 focalizzazione delle parti principali del messaggio standardizzato

 individuazione dei 3 indici di accesso alla matrice tridimensionale


strutturante l‟ organizzazione multi timbrica dello strumento elettronico

 individuazione del tipo di parametro da modificare e del numero di valori


che lo compongono

 conversione dell‟ indirizzo di memoria del parametro ricevuto

in uno valido per lo strumento elettronico

 inserimento dei nuovi valori nei relativi campi della struttura parametri
per ogni livello di sottovoci a cui si riferisce

99
Capitolo 7
27 novembre 2008

 In secondo luogo le caratteristiche tecniche dell‟ organo liturgico RODGERs


Insignia 538-WD (Appendice_B) evidenziano 4 configurazioni di registro voci
standard dello strumento:

 francese
 barocca
 inglese
 americana

L‟ applicativo d‟ interfaccia progettato si è basato esclusivamente sulle voci di


registro della configurazione barocca come risulta evidente dal paragrafo 4.2
dall‟ analisi del file baroque.cpp. Nella strutturazione delle altre voci di registro
(francese, inglese, americana) i cambiamenti sono riscontrabili esclusivamente
nell‟ organizzazione dei sottolivelli di RANK e VOICE PALETTE mantenendo la
strutturazione standard già analizzata per la configurazione barocca.

Si potrebbero così integrare nella GUI le nuove funzionalità di accesso alle 4


configurazioni di registro voci tramite 3 semplici operazioni:

 inclusione nel devoloper studio dei files contenenti la strutturazione delle


4 configurzioni (es. french.cpp, english.cpp,america.cpp)
 implementazione nella finestra di dialog principale di una nuova combo
box per la scelta di una delle 4 configurazioni da parte dell‟ utente
 caricamento in RAM della configurazione selezionata

In particolare, l‟ ultimo punto è facilmente implementabile riprendendo il codice


sorgente già sviluppato (visionato nel paragrafo 5.2), operando l‟ inizializzazione
dei dati in RAM con 4 funzioni diverse simili alla CaricaBaroqueRom(); si
diversificano solo le strutture di origine prese da uno dei 4 files (baroque.cpp,
french.cpp, english.cpp,american.cpp).

 L‟ ultima prerogativa di sviluppo futuro dell‟ applicativo GUI EDITOR si


incentra sui miglioramenti d‟ interfacciamento con l‟ hardware esterno apportabili
nell‟ ambito di interoperatività con l‟ intera gamma dei prodotti RODGERs.

100
Capitolo 7
27 novembre 2008

Di seguito è possibile prendere in esame le tipologie di organi liturgici della


famiglia RODGERs prodotti dall‟ azienda ROLAND .

Essi si distinguono principalmente per un diverso numero di manuali (tastiere)


con cui risultano strutturati, consentendone la seguente classificazione:

101
Capitolo 7
27 novembre 2008

 Organi a 2 MANUALI
 Organi a 3 MANUALI
 Organi a 4 MANUALI
 Organi a 5 MANUALI

Tutte le 4 tipologie (ognuna caratterizzata da più modelli) possiedono una


configurazione di registro delle voci simile a quella analizzata per il RODGERs
i538 (par. 4.2) e le variazioni possibili riguardano il numero di voci di registro
principali e il numero dei livelli del “RANK”, ovvero di canne simulate dall‟
organo; mentre la quantità e le tipologie di parametri interni editabili (per ogni
singola voce) rimangono sostanzialmente invariate, conservando la strutturazione
riscontrata per il Rodgers i538 (par 4.2)
Appare estremamente interessante l‟ idea di poter usufruire di un GUI EDITOR
“universale” capace di offrire un interfacciamento con l‟ intera gamma di organi
RODGERs.

Si potrebbe ipotizzare un‟ interfaccia di tipo modulare in grado di cambiare


l‟ aspetto grafico e funzionale in base alla tipologia e al modello di organo con cui
si desidera operare una comunicazione midi.
L‟ operazione più lunga e complicata da implementare sarebbe quella di crearsi
una dialog per ogni modello della gamma RODGERs; ciascuna finestra
presenterebbe le sembianze estetiche del modello a cui si riferisce ripetendo le
operazioni già collaudate con l‟ interfaccia del RODGERs i538 (par. 5.2). Nell‟
applicativo ogni finestra sarebbe richiamabile tramite un idoneo codice
identificativo simile a quello usato per l‟ i538 del tipo:
“IDD_DIALOG_RODGERs_XX” (la sigla XX indica il modello relativo alla
finestra considerata).
All‟ utente sarà consentita la scelta della tipologia e del modello di organo con cui
interagire mediante un‟ interfaccia iniziale formalizzabile nel seguente schema:

102
Capitolo 7
27 novembre 2008

FINESTRA INIZIALE: L’ UTENTE


SCEGLIE TIPOLOGIA E MODELLO DI
ORGANO CON CUI COMUNICARE

FINESTRA (o più) RELATIVA AL


MODELLO SELEZIONATO

EDITING EDITING
PARAMETRI PARAMETRI
VOCE NOTA

La struttura rispecchia molto quella individuabile in figura 4.2 preponendo come


elemento aggiuntivo l‟ interfaccia di selezione del tipo di strumento a cui l‟ utente
intende interfacciarsi.

Aspetto non meno rilevante risulterebbe la costruzione grafica delle dialogs


relative all‟ intera gamma RODGERs. Prendendo, ad esempio, un organo liturgico
con 5 manuali si presenterebbe la problematica di visualizzare ben 6 sezioni di
tasti nell„ interfaccia (il doppio rispetto a quelle dell‟ i538); sicuramente i tools di
sviluppo offerti dal VISUAL C++ e delle MFC propongono svariati espedienti
d‟ implementazione e solo un vero e proprio studio approfondito permetterebbe di
individuare la soluzione più congeniale a questa e alle altre tematiche di
architettura di programmazione.

In conclusione le potenzialità di sviluppo del GUI EDITOR elencate mettono in


risalto le qualità del software sviluppato, facendo risaltare la dedizione riposta
nell‟ intera conduzione dell‟ attività, portando a compimento gli obbiettivi
prefissati in tale tesi sperimentale.

La grande passione per l‟argomento e l‟ impegno da me profuso, unito alle


competenze del personale altamente specializzato che mi ha accompagnato e mi
ha affiancato in questo percorso formativo, hanno arricchito le mie conoscenze,
sviluppando nuove applicazioni, approfondendo e contestualizzando le nozioni
che questa università mi ha trasmesso nel corso del mio ciclo di studi.

103
27 novembre 2008

104
APPENDICE A
27 novembre 2008

- APPENDICE A -

Strutturazione schematica di un sintetizzatore

Caratteristica Descrizione
Definibile anche come politimbricità : si intende la
MULTITIMBRICITÀ capacità di generare simultaneamente diverse
timbriche, assegnando a ciascuna di esse un numero
variaile delle voci polifoniche a disposizione.
E‟ defininibile come un dispositivo hardaware (ma
oggi è molto utilizzato anche la tipologia software)
SEQUENCER che permette di creare e produrre delle sequenze di
segnal idi controllo per comandare uno strumento
elettronico

Si intende il numero di note (assegnate a uno o più


timbri) suonabili nello stesso istante. Gli strumenti
POLIFONIA moderni hanno molta più polifonia dei sintetizzatori
Vintage raggiungendo anche 128 o più note suonabili
contemporaneamente.

L‟ unità effetti integrata si avvale di un apposito


UNITÀ EFFETTI processore di segnali definito digital signal processing
(DSP) applicando effetti come chorus, delay, pictch,
INTEGRATA (DSP) reverbero sui suoni generati internamente o su fonti
esterne dall‟ ingresso audio (analogico o digitale).

Un synth (sintetizzatore) può possedere diverse


CONNESSIONI tipologie di connessioni audio: analogiche e digitali.
AUDIO Ciò permette molteplici caratteristiche di
collegamento con diversi dispositivi esterni.

Solitamente ogni strumento è dotato di almeno una


CONNESSIONI MIDI porta di MIDI-IN e una di MIDI-OUT. E‟ possibile
riscontrare la presenza di più porte per l‟ interazione.
con più device esterni.

105
APPENDICE B
27 novembre 2008

- APPENDICE B -

106
APPENDICE C_1
27 novembre 2008

- APPENDICE C_1-

Files di progetto per la costruzione della dialog relativa alle voci della lista
bottoni del par. 5.6.
InsertVoce("8'Voce Umana");
InsertVoce("8' Gemshorn Celeste II");
InsertVoce("8' Flute Harmonique");
InsertVoce("8' Rohrflote");
InsertVoce("8' Gemshorn");
InsertVoce("8' Flauto Dolce");
InsertVoce("8' Flute Celeste");
InsertVoce("8' Unda Maris II");
InsertVoce("4' Octave");
InsertVoce("4' Gedacktflote");
InsertVoce("2' 2/3 Nasat");
InsertVoce("2' Superoctave");
InsertVoce("2' Waldflote");
InsertVoce("1' 1/3 Quint");
InsertVoce("Sesquialtera II");
InsertVoce("1' 3/5 Terz");
InsertVoce("IV - V Mi xture");
InsertVoce("III Sharf");
InsertVoce("16' Posaune");
InsertVoce("8' Trompete");
InsertVoce("8' Trompette Harmonique");
InsertVoce("8' Krummhorn");
InsertVoce("8' French Horn");
InsertVoce("8' Klarine");
InsertVoce("Harp");
InsertVoce("Carillon");
InsertVoce("Harpsichord");
InsertVoce("Piano");
InsertVoce("Great Tremulant");
InsertVoce("16' Great to Great");
InsertVoce("4' Great to Great");
InsertVoce("4' Flauto Dolce");
InsertVoce("4' Flauto Celeste");
InsertVoce("_spare_");
InsertVoce("8' Prestant");
InsertVoce("8' Gedackt");
InsertVoce("4' Principal");
InsertVoce("4' Koppeflote");
InsertVoce("2' 2/3 Nasard");
InsertVoce("2' Oktave");
InsertVoce("1' 1/3 Spitzquinte");
InsertVoce("1' Sifflote");
InsertVoce("III -IV Sharf");
InsertVoce("16' Dulzian");
InsertVoce("8' Krummhorn");
InsertVoce("Harpsichord");
InsertVoce("Positiv tremulant");
InsertVoce("positiv Unisson Off");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("16' Bourdon Doux");
InsertVoce("String");
InsertVoce("8' Viola Pomposa");
InsertVoce("8' Viola Celeste");
InsertVoce("8' Viola Celeste II");
InsertVoce("8' Muted Viols II");

107
APPENDICE C_1
27 novembre 2008

InsertVoce("8' Bourdon");
InsertVoce("8' Flauto Dolce");
InsertVoce("8' Flute Celeste");
InsertVoce("8' Flute Celeste II");
InsertVoce("8' Gamba");
InsertVoce("8' Echo Gamba");
InsertVoce("4' Principal");
InsertVoce("4' Nachthorn");
InsertVoce("2' 2/3 Nasard");
InsertVoce("2' Doublette");
InsertVoce("2' Blockflote");
InsertVoce("1' 3/5 Tierce");
InsertVoce("1' Sifflote");
InsertVoce("Sesquialtera II");
InsertVoce("IV Plein jeu");
InsertVoce("III C ymbale");
InsertVoce("Contre Basson");
InsertVoce("8' Festival Trumpet");
InsertVoce("8' Trompette");
InsertVoce("8' Hautbois");
InsertVoce("8' Voix Humaine (mf)");
InsertVoce("8' Voix Humaine (mp)");
InsertVoce("4' Clairon");
InsertVoce("Swell Tremulant");
InsertVoce("16' swell to swell");
InsertVoce("Swell Unison off");
InsertVoce("4' swell to swell");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("Pedal Chamade");
InsertVoce("Choir Chamade");
InsertVoce("Great Chamade");
InsertVoce("Swell Chamade");
InsertVoce("Solo Chamade");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("16' Contre Erzahler");
InsertVoce("8' Salicional");
InsertVoce("8' Viola Celeste");
InsertVoce("8' Hohflote");
InsertVoce("8' Echo Celeste II");
InsertVoce("4' Spitzpincipal");
InsertVoce("4' Lieblichflote");
InsertVoce("4' Octave Erzahler");
InsertVoce("2' 2/3 Nasard");
InsertVoce("2' Octave");
InsertVoce("2' Flachflote");
InsertVoce("1' 1/3 Quintflote");
InsertVoce("1' Sifflote");
InsertVoce("Mouted Cornet III");
InsertVoce("III Mi xture");
InsertVoce("8' Troumpette Harmonique");
InsertVoce("8' Major Tuba");
InsertVoce("8' Krummhorn");
InsertVoce("8' Harpsichord");
InsertVoce("8' Harp");
InsertVoce("Choir Tremulant");
InsertVoce("16' choir tp choir");
InsertVoce("Choir Unison off");
InsertVoce("4' choir tp choir");
InsertVoce("8' Concert Flute");
InsertVoce("8' Erzhler");

108
APPENDICE C_1
27 novembre 2008

InsertVoce("8' Erzhler CelesteII");


InsertVoce("8' Flauto Mirabilis");
InsertVoce("8' Gross Gamba");
InsertVoce("8' Gamba Celeste");
InsertVoce("4' Doppelflute");
InsertVoce("2' 2/3 Flute twelfth");
InsertVoce("2' Piccolo");
InsertVoce("Grand jeu VIII");
InsertVoce("16' Contre Bombarde");
InsertVoce("8' Fanfare Trumpet");
InsertVoce("8' Tube Mirabilis");
InsertVoce("8' English horn");
InsertVoce("8' French horn");
InsertVoce("8' Clarinet");
InsertVoce("4' Clarion Harmonique");
InsertVoce("Carillon");
InsertVoce("Solo Tremulant");
InsertVoce("16' Solo to Solo");
InsertVoce("Solo Unison Off");
InsertVoce("4' Solo to Solo");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("32' Contra Pincipal");
InsertVoce("32' Contre Bourdon");
InsertVoce("16' Major Bass");
InsertVoce("16' Principal");
InsertVoce("16' Subass");
InsertVoce("16' Violone");
InsertVoce("16' Gemshorn");
InsertVoce("16' Bourdon Doux");
InsertVoce("16' Erzahler");
InsertVoce("8' Octave");
InsertVoce("8' Violoncello");
InsertVoce("8' Gedackt Pommer");
InsertVoce("8' Bourdon (sw)");
InsertVoce("4' Choralbass");
InsertVoce("4' Gedacktpfeife");
InsertVoce("2' Kleinflote");
InsertVoce("IV Mi xture");
InsertVoce("V Harmonics");
InsertVoce("III Cornet");
InsertVoce("32' Contre Bombarde");
InsertVoce("32' Contre Basson");
InsertVoce("16' Bombarde");
InsertVoce("16' Pousane (gt)");
InsertVoce("16' Basson");
InsertVoce("8' Trompette");
InsertVoce("Oktave Pousane (gt)");
InsertVoce("4' Clarion");
InsertVoce("4' Krummhorn");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("8' Great to Pedal");
InsertVoce("4' Great to Pedal");
InsertVoce("8' swell to Pedal");
InsertVoce("4' swell to Pedal");
InsertVoce("8' Choir to Pedal");
InsertVoce("4' Choir to Pedal");
InsertVoce("8' Solo to Pedal");
InsertVoce("4' Solo to Pedal");
InsertVoce("8' Positiv to Pedal");
InsertVoce("16' Swell to Great");

109
APPENDICE C_1
27 novembre 2008

InsertVoce("8' Swell to Great");


InsertVoce("4' Swell to Great");
InsertVoce("16' Choir to Great");
InsertVoce("8' Choir to Great");
InsertVoce("4' Choir to Great");
InsertVoce("16' Solo to Great");
InsertVoce("8' Solo to Great");
InsertVoce("4' Solo to Great");
InsertVoce("16' Positiv to Great");
InsertVoce("8' Positiv to Great");
InsertVoce("16' Swell to Choir");
InsertVoce("8' Swell to Choir");
InsertVoce("4' Swell to Choir");
InsertVoce("16' Solo to Choir");
InsertVoce("8' Solo to Choir");
InsertVoce("4' Solo to Choir");
InsertVoce("Positiv Off Choir");
InsertVoce("16' Choir to Swell");
InsertVoce("8' Choir to Swell");
InsertVoce("4' Choir to Swell");
InsertVoce("8' Solo to Swell");
InsertVoce("Positiv Off Swell");
InsertVoce("8' Positiv to Swell");
InsertVoce("8' Positiv to Swell");
InsertVoce("8' Positiv to Solo");
InsertVoce("Great tuttu on Solo");
InsertVoce("Pipe Tremulant");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("All Pipes Off");
InsertVoce("All Ancillary On");
InsertVoce("Main Tremulant");
InsertVoce("Flute Tremulant Full");
InsertVoce("Great/pedal Ancillary On");
InsertVoce("Choir Pipes Off");
InsertVoce("Choir Ancillary On");
InsertVoce("Main Off");
InsertVoce("Antiphonal On");
InsertVoce("Swell Pipes Off");
InsertVoce("Festival Trumpet FF");
InsertVoce("Swell Ancillary On");
InsertVoce("Zimbelstern");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");

110
APPENDICE C_2
27 novembre 2008

- APPENDICE C_2 -

FIles di progetto per la costruzione della dialog relativa alla lista di bottoni (par.
5.6)

FILE ButtonListBox.cpp

// ButtonListBox.cpp : implementation file


//

#include "stdafx.h"
#include "ButtonListBox.h"
#include "Global.h"

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

bool acceso;

/////////////////////////////////////////////////////////////////////////////
// CButtonListBox

CButtonListBox::CButtonListBox()
{
}

CButtonListBox::~CButtonListBox()
{
for(int i=0; i<= m_ButtonArray.GetUpperBound();i ++)
delete m_ButtonArray.ElementAt(i);
}

///////////////////////////////////////////////////////////////////
/////Creazione di un nuovo elemento (bottone) all' interno/////////
/////della lista bottoni inserendo la stringa e l' id relativi/////
///////////////////////////////////////////////////////////////////
void CButtonListBox::AddItem(LPCTSTR ButtonText,long idButton)
{

CLedButton* pAddedButton;
static int count = 0;
CRect rect;
CRect ButtonRect;

count++;
GetClientRect( rect );

pAddedButton = new CLedButton(ButtonText,idButton,this);


ButtonRect.SetRect( 0, 0, rect.Width(), (rect.Height() /
NUMBER_OF_BUTTONS_IN_LIST_VIEW) );

111
APPENDICE C_2
27 novembre 2008

pAddedButton->Create( "", WS_CHILD|BS_OWNERDRAW, ButtonRect, this,


1001+count );

int AddedAt = m_ButtonArray.Add( p AddedButton );

//Adds a string and assigns nIndex the index of the current item
int nIndex = AddString( "" );

// Set a hight for the data item


CListBox::SetItemHeight( nIndex, rect.Height() /
NUMBER_OF_BUTTONS_IN_LIST_VIEW );

//If no error, associates the index with the button


if( nIndex!=LB_ERR && nIndex!=LB_ERRSPACE )
SetItemData( nIndex, (DWORD)m_ButtonArray.ElementAt(AddedAt) );
}

BEGIN_MESSAGE_ MAP(CButtonListBox, CListBox)


//{{AFX_ MSG_ MAP(CButtonListBox)
ON_WM_DRAWITEM_REFLECT()
ON_WM_ERASEBKGND()
//}}AFX_ MSG_ MAP
END_MESSAGE_ MAP()

/////////////////////////////////////////////////////////////////////////////
// CButtonListBox message handlers

void CButtonListBox::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class

CListBox::PreSubclassWindow();
}

void CButtonListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)


{
CRect LedButtonRect = lpDrawItemStruct->rcItem; //Gets the rect of the item

CLedButton* pLedButton = reinterpret_cast<CLedButton*>(lpDrawItemStruct-


>itemData);

if(!pLedButton)
return;

pLedButton->MoveWindow(LedButtonRect);
pLedButton->CentreLED();
pLedButton->ShowWindow( SW_SHOW );

BOOL CButtonListBox::OnEraseBkgnd(CDC* pDC)


{
// Doing this speeds up drawing apparently
//return CWnd::OnEraseBkgnd(pDC);
return TRUE;
}

//////////////////////////////////////////////////////////////////
////Gestione evento di attivazione o disattivazione di una////////
////singola voce (accensione o spegnimento led corrispondete)////
///all' interno della listbox////////////////////////////////////

112
APPENDICE C_2
27 novembre 2008

/////////////////////////////////////////////////////////////////
BOOL CButtonListBox::PreTranslateMessage(MSG* pMsg)
{
CLedButton* pButton = NULL;

CWnd* Parent = NULL;

Parent = GetParent();//(?????)

//Se ricevo un messaggio di click su una voce verifico se tale voce deve
//essere spenta o accesa (a seconda dello stato iniziale)
if(pMsg->message == UM_BUTTON_CLICK)
{
pButton = (CLedButton*)pMsg->lParam;

if(pButton->GetLed()->GetLedMode() == CLed::LED_ON)//se la voce è


accesa
{
pButton->GetLed()-
>SetLed(CLed::LED_COLOR_YELLOW,CLed::LED_OFF,CLed::LED_ROUND);

//spegnimento voce
}
else
{
pButton->GetLed()-
>SetLed(CLed::LED_COLOR_RED,CLed::LED_ON,CLed::LED_ROUND);

//accensione voce
}

acceso = false;
acceso = pButton->GetLed()->GetLedMode()==CLed::LED_ON;

CString sel = pButton->GetButtonText();


// L' id del bottone selezionato viene assegnato a idsel
// entrambi i valori hanno un range da 0 a 244
long idSel = pButton->GetButtonId();

if(Parent)
{ //In vio alla finestra di un messaggio definito WM_SEND_PARAM
// e il secondo messaggio (idSel) relativo all' ID del bottone
//cliccato
::PostMessage(Parent-
>m_hWnd,WM_SEND_PARAM,idSel,(DWORD)this);
}
}

return CListBox::PreTranslateMessage(pMsg);
}

FILE Led.cpp
#include "stdafx.h"
#include "resource.h"
#include "Led.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE

113
APPENDICE C_2
27 novembre 2008

static char THIS_FILE[] = __FILE__;


#endif

/////////////////////////////////////////////////////////////////////////////
// CLed
#define TIMER_ID_PING 1 // Timer Ping ID
#define TIMER_ID_FLASH 2 // Flash Timer ID

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
CLed::CLed()
{
m_LedBitmap.LoadBitmap(IDB_LEDS);
m_nLedColor = LED_COLOR_RED;
m_nLedMode = LED_OFF;
m_nLedShape = LED_ROUND;
m_Flashing = FALSE;

CLed::~CLed()
{
VERIFY(m_LedBitmap.DeleteObject());
}

BEGIN_MESSAGE_ MAP(CLed, CStatic)


//{{AFX_ MSG_ MAP(CLed)
ON_WM_PAINT()
ON_WM_TIMER()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
//}}AFX_ MSG_ MAP
END_MESSAGE_ MAP()

/////////////////////////////////////////////////////////////////////////////
// CLed message handlers

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void CLed::OnPaint()
{
CPaintDC dc(this); // device context for painting
DrawLed(&dc,m_nLedColor,m_nLedMode,m_nLedShape);

// Do not call CStatic::OnPaint() for painting messages


}

///////////////////////////////////////////////////////////////////////////////
// Name: SetLed
// Description: This method will draw the LED to the specified DC.
//
// Entry:
// CDC *pDC - DC to draw to
//
// int iLedColor - Where color is defined by:
// LED_COLOR_RED
// LED_COLOR_GREEN
// LED_COLOR_YELLOW
// LED_COLOR_BLUE
//
// int iMode - where mode is defined by:

114
APPENDICE C_2
27 novembre 2008

// LED_ON
// LED_OFF
// LED_DISABLED
//
// int iShape - where shape is defined by:
// LED_ROUND
// LED_SQUARE
///////////////////////////////////////////////////////////////////////////////
void CLed::DrawLed(CDC *pDC,int nLEDColor, int nMode, int nShape)
{
CRect rect;
GetClientRect(&rect);

//
// Center led within an oversized window
//
if(rect.Width() >= LED_SIZE && rect.Height() >= LED_SIZE)
{
int nWidth = rect.Width();
int nHeight = rect.Height();
rect.left += (nWidth - LED_SIZE)/2;
rect.right -= (nWidth - LED_SIZE)/2;
rect.top += (nHeight - LED_SIZE)/2;
rect.bottom -= (nHeight - LED_SIZE)/2;
}

//
// Prepare temporary DCs and bitmaps
//
CBitmap TransBitmap;
TransBitmap.CreateBitmap(LED_SIZE,LED_SIZE,1,1,NULL);
CBitmap bitmapTemp;
CBitmap* pBitmap = &m_LedBitmap;
CDC srcDC;
CDC dcMask;
CDC TempDC;
TempDC.CreateCompatibleDC(pDC);
srcDC.CreateCompatibleDC(pDC);
dcMask.CreateCompatibleDC(pDC);

CBitmap* pOldBitmap = srcDC.SelectObject(pBitmap);


CBitmap* pOldMaskbitmap = dcMask.SelectObject(&TransBitmap);
bitmapTemp.CreateCompatibleBitmap(pDC,LED_SIZE,LED_SIZE);

//
// Work with tempDC and bitmapTemp to reduce flickering
//
CBitmap *pOldBitmapTemp = TempDC.SelectObject(&bitmapTemp);
TempDC.BitBlt(0, 0, LED_SIZE, LED_SIZE, pDC, rect.left, rect.top, SRCCOPY);

//
// Create mask
//
COLORREF OldBkColor = srcDC.SetBkColor(RGB(255,0,255));
dcMask.BitBlt(0, 0, LED_SIZE, LED_SIZE,&srcDC, nMode*LED_SIZE,
nLEDColor+nShape, SRCCOPY);
TempDC.SetBkColor(OldBkColor);

//
// Using the IDB_LEDS bitmap, index into the bitmap for the appropriate
// LED. By using the mask color (RGB(255,0,255)) a mask has been created
// so the bitmap will appear transparent.
//

115
APPENDICE C_2
27 novembre 2008

TempDC.BitBlt(0, 0, LED_SIZE, LED_SIZE, &srcDC, nMode*LED_SIZE,


nLEDColor+nShape, SRCINVERT);
TempDC.BitBlt(0, 0, LED_SIZE, LED_SIZE,&dcMask, 0, 0, SRC AND);
TempDC.BitBlt(0, 0, LED_SIZE, LED_SIZE, &srcDC, nMode*LED_SIZE,
nLEDColor+nShape, SRCINVERT);

//
// Since the actual minipulation is done to tempDC so there is minimal
// flicker, it is now time to draw the result to the screen.
//
pDC->BitBlt(rect.left, rect.top, LED_SIZE, LED_SIZE, &TempDC, 0, 0,
SRCCOPY);

//
// House cleaning
//
srcDC.SelectObject(pOldBitmap);
dcMask.SelectObject(pOldMaskbitmap);
TempDC.SelectObject(pOldBitmapTemp);
VERIFY(srcDC.DeleteDC());
VERIFY(dcMask.DeleteDC());
VERIFY(TempDC.DeleteDC());
VERIFY(TransBitmap.DeleteObject());
VERIFY(bitmapTemp.DeleteObject());
}

///////////////////////////////////////////////////////////////////////////////
// Name: SetLed
// Description: This method will draw and set led parameters.
//
// Entry: int iLedColor - Where color is defined by:
// LED_COLOR_RED
// LED_COLOR_GREEN
// LED_COLOR_YELLOW
// LED_COLOR_BLUE
//
// int iMode - where mode is defined by:
// LED_ON
// LED_OFF
// LED_DISABLED
//
// int iShape - where shape is defined by:
// LED_ROUND
// LED_SQUARE
///////////////////////////////////////////////////////////////////////////////
void CLed::SetLed(int nLedColor, int nMode, int nShape)
{
m_nLedColor = nLedColor;
m_nLedMode = nMode;
m_nLedShape = nShape;

CDC *pDC;
pDC = GetDC();
DrawLed(pDC,m_nLedColor,m_nLedMode,m_nLedShape);
ReleaseDC(pDC);
}

///////////////////////////////////////////////////////////////////////////////
// Name: Ping
// Description: This method will turn the led on for dwTimeout milliseconds and
// then turn it off.
//
// Entry: DWORD dwTimeout - Time out in milliseconds
///////////////////////////////////////////////////////////////////////////////

116
APPENDICE C_2
27 novembre 2008

void CLed::Ping(DWORD dwTimeout)


{
// Return if pinging
if(m_bPingEnabled == TRUE)
{
KillTimer(TIMER_ID_PING);
}

m_bPingEnabled = TRUE;
SetLed(m_nLedColor,CLed::LED_ON,m_nLedShape);
SetTimer(TIMER_ID_PING,dwTimeout,NULL);

void CLed::Flash(DWORD dwTimeout)


{
m_FlashRate = dwTimeout;
SetLed(m_nLedColor,CLed::LED_ON,m_nLedShape);
SetTimer(TIMER_ID_FLASH,dwTimeout,NULL);
m_Flashing = TRUE;
}

void CLed::SetLedState(BOOL state)


{
if(state)
SetLed(m_nLedColor,CLed::LED_ON,m_nLedShape);
else
SetLed(m_nLedColor,CLed::LED_OFF,m_nLedShape);

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void CLed::OnTimer(UINT nIDEvent)
{
if(nIDEvent == TIMER_ID_PING)
{
SetLed(m_nLedColor,CLed::LED_OFF,m_nLedShape);
KillTimer(nIDEvent);
m_bPingEnabled = FALSE;
}
else if(nIDEvent == TIMER_ID_FLASH)
{
if(GetLedMode() == LED_OFF)
SetLed(m_nLedColor,CLed::LED_ON,m_nLedShape);
else
{
if(GetLedMode() == LED_ON)

SetLed(m_nLedColor,CLed::LED_OFF,m_nLedShape);
}

KillTimer(nIDEvent);

SetTimer(TIMER_ID_FLASH,m_FlashRate,NULL);
}

CStatic::OnTimer(nIDEvent);
}

///////////////////////////////////////////////////////////////////////////////

117
APPENDICE C_2
27 novembre 2008

///////////////////////////////////////////////////////////////////////////////
BOOL CLed::OnEraseBkgnd(CDC* pDC)
{
// No background rendering
return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

FILE SelezioneVociMultiple.Dlg

// SelezioneVociMultipleDlg.cpp : implementation file


//

#include "stdafx.h"
#include "RODGERS_i385_GUI.h"
#include "SelezioneVociMultipleDlg.h"
#include <stdio.h>
#include "conio.h"
#include "windows.h"
#include "mmsystem.h"
#include "voicedata.h"
#include "SLIDERDlg.h"
#include "Global.h" //mdr_par
#include "ButtonListBox.h"

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

extern unsigned char midi_voci[44];


extern bool acceso;
extern int midi_device;

/////////////////////////////////////////////////////////////////////////////
// CSelezioneVociMultipleDlg dialog

CSelezioneVociMultipleDlg::CSelezioneVociMultipleDlg(CWnd* pParent /*=NULL*/)


: CDialog(CSelezioneVociMultipleDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSelezioneVociMultipleDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}

void CSelezioneVociMultipleDlg::DoDataExchange(CDataExchange* pDX)


{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSelezioneVociMultipleDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
DDX_Control(pDX, IDC_BUTTON_LIST, m_ButtonListBox);
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_ MAP(CSelezioneVociMultipleDlg, CDialog)


//{{AFX_ MSG_ MAP(CSelezioneVociMultipleDlg)
ON_MESSAGE( WM_SEND_PARAM, OnSendParam ) //mdr_par (?????)

118
APPENDICE C_2
27 novembre 2008

ON_WM_PAINT()
//}}AFX_ MSG_ MAP
END_MESSAGE_ MAP()

///////////////////////////////////////////////////////////////////////////////////////
///////////////////SETTAGGIO BIT DELLE VOCI SELEZIONATE////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
LRESULT CSelezioneVociMultipleDlg::OnSendParam(WPARAM wParam, LPARAM
lParam)
{
long idSel=wParam;//id del pulsante selezionato

int param_1,param_2;
unsigned char param_3;

param_1 = (idSel/7) + 7; // individua il numero del byte (considerando che i primi


)su cui andare a scrivere all' interno del midi_voci aray
param_2 = idSel%7; // individua il numero del bit da settare ad 1 oppure a 0
relativo alla voce selezionata/deselezionata

param_3 = 0;// converte il numero in esadecimale

switch(param_2) {

case 0: // Bit 0 settato a 1


param_3 = 0x01;
break;

case 1: // Bit 1 settato a 1


param_3 = 0x02;
break;

case 2: // Bit 2 settato a 1


param_3 = 0x04;
break;

case 3: // Bit 3 settato a 1


param_3 = 0x08;
break;

case 4: // Bit 4 settato a 1


param_3 = 0x10;
break;

case 5: // Bit 5 settato a 1


param_3 = 0x20;
break;
case 6: // Bit 6 settato a 1
param_3 = 0x40;
break;

if(acceso)
{
midi_voci[param_1] = midi_voci[param_1] | param_3;//Settaggio del bit
corrisondente a 1.Si effettua l' OR col byte corrispondente in modo di lasciare a 0 (o a 1)
gli altri bit già eventualmente impostati.
}
else

119
APPENDICE C_2
27 novembre 2008

{
midi_voci[param_1] = midi_voci[param_1] - param_3;//Settaggio del bit
corrispondente a 0.
}

SendSysex();//In vio del messaggio esclusivo midi_voci[]

return 0;
}

/////////////////////////////////////////////////////////////////////////////
// CSelezioneVociMultipleDlg message handlers

////////////////////////////////////////////////////////////////////////////
///Fun zione membro di creazione e inserimento di un nuovo elemento/////////
///all' interno della lista di bottoni dove ognuno identifica una voce/////
///Con la InsertVoce passo la stringa "name" con cui AddItem crea una //////
///nuova instanza contraddistinta da quel nome a cui assegna (in modo)/////
///progressivo un indice che rappresenta l' idButton. Tale indi ce /////////
//risulta necessario per identificare il bottone spento o acceso dall//////
///utente. ////////////////////////////////////////////////////////////////
void CSelezioneVociMultipleDlg::InsertVoce(LPCSTR name)
{
m_ButtonListBox.AddItem(name,m_curr_indice);
m_curr_indice++;
}

BOOL CSelezioneVociMultipleDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// TODO: Add e xtra initialization here


////////////////////////////////////////////////////////
//INSERIMENTO DI TUTTO L' ELENCO COMPLETO DELLE VOCI///
///in modo progressivo e ordinato rispetto allo////////
///elenco originario Roland ///////////////////////////
///////////////////////////////////////////////////////
m_curr_indice=0;
InsertVoce("unused");
InsertVoce("16'Principal");
InsertVoce("Zimbelstern");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");

...
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("Test/Tune Mode");
InsertVoce("_spare_");
InsertVoce("_spare_");
InsertVoce("_spare_");

//////TOTALE 244 VOCI//////////////////////////


///Disposte in modo progressivo su una lista///
//di altrettanti bottoni individuabili con un /

120
APPENDICE C_2
27 novembre 2008

//id progressivo //////////////////////////////


///////////////////////////////////////////////

return TRUE;
}

//////////////////////////////////////////////////////
////FOR MATTAZIONE E IN VIO MESSAGGIO ESCLUSIVO/////////
////Alla pressione di un qualsiasi pulsante della/////
//Lista bottoni (sia per accensione sia per //////////
//spegnimento di una voce) viene inviato il //////////
//messaggio midi_voci[44] contenete i bit settati/////
//ad 1 delle voci accesse ////////////////////////////

void CSelezioneVociMultipleDlg::SendSysex()
{
int i =0;
int sum ,ck ,w ;
ck = 0;

short offset=0;

int midiport;
//int rc;
HMIDIOUT device; //MIDI de vice interface for hold data for Midi messages;

// Calcolo del Checksum


sum = 0;

for (w=7 ; w <=41 ; w++)


{
sum += midi_voci[w] ;
}

sum &= 0x7F;


ck = (128 - sum)&0x7F;

//APERTURA DEVICE E PORTA MIDI PER L' INVIO DEL MESSAGGIO

midiport = midi_device;
MIDIHDR* pHeader = new MIDIHDR;
pHeader->lpData = (char *) &midi_voci[0];
pHeader->dwBufferLength = 44;
pHeader->dwBytesRecorded = 44;
pHeader->dwFlags=0;

//Apre la MIDI output


midiOutOpen(&device, midiport, 0, 0, C ALLBACK_NULL);

midiOutPrepareHeader(device , (LPMIDIHDR) pHeader, sizeof(MIDIHDR));


midiOutLongMsg(device , (LPMIDIHDR) pHeader, sizeof(MIDIHDR));
midiOutUnprepareHeader(device , (LPMIDIHDR) pHeader, sizeof(MIDIHDR));

midiOutClose(device);

}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

121
APPENDICE C_2
27 novembre 2008

void CSelezioneVociMultipleDlg::OnOK()
{
// TODO: Add e xtra validation here

CDialog::OnOK();
}

////////////////////////////////////////////////////
////BackGround BITMAP///////////////////////////////
////////////////////////////////////////////////////
void CSelezioneVociMultipleDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting

// TODO: Add your message handler code here


CBitmap bitmap;

CDC memdc;

bitmap.LoadBitmap( IDB_BACK_VOCI_ MULTIPLE );

BITMAP bmp;

bitmap.GetBitmap( &bmp );

memdc.CreateCompatibleDC( &dc );

memdc.SelectObject( &bitmap );

CRect rect;

GetClientRect(rect);

StretchBlt (dc.m_hDC,0, 0, rect.right, rect.bottom, memdc.m_hDC, 0, 0,


bmp.bmWidth, bmp.bmHeight, SRCCOPY );

122
APPENDICE D
27 novembre 2008

- APPENDICE D-

Elenco completo delle voci di resgitro relative al RODGERs i538

STOPS BYTE BIT NOME VOCE


0 0 0 unused
1 0 1 16'Principal
2 0 2 16'Flute
3 0 3 8'Principal
4 0 4 8'Voce Umana
5 0 5 8' Gemshorn Celeste II
6 0 6 8' Flute Harmonique
7 1 0 8' Rohrflote
8 1 1 8' Gemshorn
9 1 2 8' Flauto Dolce
10 1 3 8' Flute Celeste
11 1 4 8' Unda Maris II
12 1 5 4' Octave
13 1 6 4' Gedacktflote
14 2 0 2' 2/3 Nasat
15 2 1 2' Superoctave
16 2 2 2' Waldflote
17 2 3 1' 1/3 Quint
18 2 4 Sesquialtera II
19 2 5 1' 3/5 Terz
20 2 6 IV - V Mixture
21 3 0 III Sharf
22 3 1 16' Posaune
23 3 2 8' Trompete
24 3 3 8' Trompette Harmonique
25 3 4 8' Krummhorn
26 3 5 8' French Horn
27 3 6 8' Klarine
28 4 0 Harp
29 4 1 Carillon
30 4 2 Harpsichord
31 4 3 Piano
32 4 4 Great Tremulant
33 4 5 16' Great to Great
34 4 6 4' Great to Great
35 5 0 4' Flauto Dolce
36 5 1 4' Flauto Celeste
37 5 2 spare_
38 5 3 8' Prestant
39 5 4 8' Gedackt
40 5 5 4' Principal
123
APPENDICE D
27 novembre 2008

41 5 6 4' Koppeflote
42 6 0 2' 2/3 Nasard
43 6 1 2' Oktave
44 6 2 1' 1/3 Spitzquinte
45 6 3 1' Sifflote
46 6 4 III -IV Sharf
47 6 5 16' Dulzian
48 6 6 8' Krummhorn
49 7 0 Harpsichord
50 7 1 Positiv tremulant
51 7 2 positiv Unisson Off
52 7 3 spare_
53 7 4 spare_
54 7 5 16' Bourdon Doux
55 7 6 String
56 8 0 8' Viola Pomposa
57 8 1 8' Viola Celeste
58 8 2 8' Viola Celeste II
59 8 3 8' Muted Viols II
60 8 4 8' Bourdon
61 8 5 8' Flauto Dolce
62 8 6 8' Flute Celeste
63 9 0 8' Flute Celeste II
64 9 1 8' Gamba
65 9 2 8' Echo Gamba
66 9 3 4' Principal
67 9 4 4' Nachthorn
68 9 5 2' 2/3 Nasard
69 9 6 2' Doublette
70 10 0 2' Blockflote
71 10 1 1' 3/5 Tierce
72 10 2 1' Sifflote
73 10 3 Sesquialtera II
74 10 4 IV Plein jeu
75 10 5 III Cymbale
76 10 6 Contre Basson
77 11 0 8' Festival Trumpet
78 11 1 8' Trompette
79 11 2 8' Hautbois
80 11 3 8' Voix Humaine (mf)
81 11 4 8' Voix Humaine (mp)
82 11 5 4' Clairon
83 11 6 Swell Tremulant
84 12 0 16' swell to swell
85 12 1 Swell Unison off
86 12 2 4' swell to swell
87 12 3 spare_
88 12 4 spare_

124
APPENDICE D
27 novembre 2008

89 12 5 spare_
90 12 6 Pedal Chamade
91 13 0 Choir Chamade
92 13 1 Great Chamade
93 13 2 Swell Chamade
94 13 3 Solo Chamade
95 13 4 spare_
96 13 5 spare_
97 13 6 spare_
98 14 0 16' Contre Erzahler
99 14 1 8' Salicional
100 14 2 8' Viola Celeste
101 14 3 8' Hohflote
102 14 4 8' Echo Celeste II
103 14 5 4' Spitzpincipal
104 14 6 4' Lieblichflote
105 15 0 4' Octave Erzahler
106 15 1 2' 2/3 Nasard
107 15 2 2' Octave
108 15 3 2' Flachflote
109 15 4 1' 1/3 Quintflote
110 15 5 1' Sifflote
111 15 6 Mouted Cornet III
112 16 0 III Mixture
113 16 1 8' Troumpette Harmonique
114 16 2 8' Major Tuba
115 16 3 8' Krummhorn
116 16 4 8' Harpsichord
117 16 5 8' Harp
118 16 6 Choir Tremulant
119 17 0 16' choir tp choir
120 17 1 Choir Unison off
121 17 2 4' choir tp choir
122 17 3 8' Concert Flute
123 17 4 8' Erzhler
124 17 5 8' Erzhler CelesteII
125 17 6 8' Flauto Mirabilis
126 18 0 8' Gross Gamba
127 18 1 8' Gamba Celeste
128 18 2 4' Doppelflute
129 18 3 2' 2/3 Flute twelfth
130 18 4 2' Piccolo
131 18 5 Grand jeu VIII
132 18 6 16' Contre Bombarde
133 19 0 8' Fanfare Trumpet
134 19 1 8' Tube Mirabilis
135 19 2 8' English horn
136 19 3 8' French horn

125
APPENDICE D
27 novembre 2008

137 19 4 8' Clarinet


138 19 5 4' Clarion Harmonique
139 19 6 Carillon
140 20 0 Solo Tremulant
141 20 1 16' Solo to Solo
142 20 2 Solo Unison Off
143 20 3 4' Solo to Solo
144 20 4 _spare_
145 20 5 _spare_
146 20 6 _spare_
147 21 0 32' Contra Pincipal
148 21 1 32' Contre Bourdon
149 21 2 16' Major Bass
150 21 3 16' Principal
151 21 4 16' Subass
152 21 5 16' Violone
153 21 6 16' Gemshorn
154 22 0 16' Bourdon Doux
155 22 1 16' Erzahler
156 22 2 8' Octave
157 22 3 8' Violoncello
158 22 4 8' Gedackt Pommer
159 22 5 8' Bourdon (sw)
160 22 6 4' Choralbass
161 23 0 4' Gedacktpfeife
162 23 1 2' Kleinflote
163 23 2 IV Mixture
164 23 3 V Harmonics
165 23 4 III Cornet
166 23 5 32' Contre Bombarde
167 23 6 32' Contre Basson
168 24 0 16' Bombarde
169 24 1 16' Pousane (gt)
170 24 2 16' Basson
171 24 3 8' Trompette
172 24 4 Oktave Pousane (gt)
173 24 5 4' Clarion
174 24 6 4' Krummhorn
175 25 0 _spare_
176 25 1 _spare_
177 25 2 _spare_
178 25 3 8' Great to Pedal
179 25 4 4' Great to Pedal
180 25 5 8' swell to Pedal
181 25 6 4' swell to Pedal
182 26 0 8' Choir to Pedal
183 26 1 4' Choir to Pedal
184 26 2 8' Solo to Pedal

126
APPENDICE D
27 novembre 2008

185 26 3 4' Solo to Pedal


186 26 4 8' Positiv to Pedal
187 26 5 16' Swell to Great
188 26 6 8' Swell to Great
189 27 0 4' Swell to Great
190 27 1 16' Choir to Great
191 27 2 8' Choir to Great
192 27 3 4' Choir to Great
193 27 4 16' Solo to Great
194 27 5 8' Solo to Great
195 27 6 4' Solo to Great
196 28 0 16' Positiv to Great
197 28 1 8' Positiv to Great
198 28 2 16' Swell to Choir
199 28 3 8' Swell to Choir
200 28 4 4' Swell to Choir
201 28 5 16' Solo to Choir
202 28 6 8' Solo to Choir
203 29 0 4' Solo to Choir
204 29 1 Positiv Off Choir
205 29 2 16' Choir to Swell
206 29 3 8' Choir to Swell
207 29 4 4' Choir to Swell
209 29 5 8' Solo to Swell
209 29 6 Positiv Off Swell
210 30 0 8' Positiv to Swell
211 30 1 8' Positiv to Swell
212 30 2 8' Positiv to Solo
213 30 3 Great tuttu on Solo
214 30 4 Pipe Tremulant
215 30 5 _spare_
216 30 6 _spare_
217 31 0 _spare_
218 31 1 All Pipes Off
219 31 2 All Ancillary On
220 31 3 Main Tremulant
221 31 4 Flute Tremulant Full
222 31 5 Great/pedal Ancillary On
223 31 6 Choir Pipes Off
224 32 0 Choir Ancillary On
225 32 1 Main Off
226 32 2 Antiphonal On
227 32 3 Swell Pipes Off
228 32 4 Festival Trumpet FF
229 32 5 Swell Ancillary On
230 32 6 Zimbelstern
231 33 0 spare_
232 33 1 _spare_

127
APPENDICE D
27 novembre 2008

233 33 2 _spare_
234 33 3 _spare_
235 33 4 _spare_
236 33 5 _spare_
237 33 6 _spare_
238 34 0 _spare_
239 34 1 _spare_
240 34 2 _spare_
241 34 3 Test/Tune Mode
242 34 4 _spare_
243 34 5 _spare_
244 34 6 _spare_

128
27 novembre 2008

129
BIBLIOGRAFIA
27 novembre 2008

9. - BIBLIOGRAFIA

1
Mike Blaszczak, “Professional MFC with Visual C++ 6”, Asad Altimeemy , Sep 2000.

2
Microsoft Press and Microsoft Corporation, “Microsoft Visual C++: C Language
Reference (Microsoft Visual C++)”, Paperback, Jul 1996.

3
Richard P. Braden, “C to C++ Conversion: For Users of Microsoft Visual C++
Development System for Windows (Hands-on Windows Programming Series/Richard
P. Braden, Bk 8)”, Paperback, 1996.

4
Richard M. Jones, “Introduction to MFC Programming with Visual C++ (Microsoft
Technologies Series)”, Paperback, 2000.

5
Harvey M. Deitel, Paul J. Deitel, Tem Nieto, and Edward Strassberger, "Getting Started
with Microsoft Visual C++ 6 with an Introduction to MFC (2nd Edition)", Paperback,
2000.

6
Microsoft Corporation, "Microsoft Visual C++ 6.0 Reference Library (Microsoft
Professional Edition)", Paperback, 1998.

7
Microsoft Corporation, "Mastering - MFC Development Using Microsoft Visual C++
6.0", Mondadori Informatica, 2000.

8
Robert Guérin, “L'interfaccia digitale per gli strumenti musicali”, Apogeo, 2003.

9
SWANKE JOHN E., “VISUAL C++ MFC PROGRAMMING BY EXAMPLE”, CMP BOOKS,
1999

10
Jeff Prosise, "Programming Windows® with MFC, Second Edition", Microsoft Press,
1999.

11
M. Mattioli, M. Matteuzzi, "Fare Musica con il PC", Hoepli, 1999).

12
Enrico Cosimi, “Analog & Virtual Analog. Come funziona un sintetizzatore”, Il
Musichiere, 2003.

13
Roland Europe S.p.a ,C.D. Gelatt, M.P. Vecchi, “Manuele interno all’ azienda:
implementazione MIDI”, 2000.

14
Roland Europe S.p.a , “Manuele interno all’ azienda: caratteristiche tecniche di
funzionamento dell’ organo liturgico RODGERs i538”, 2006.

130
27 novembre 2008

131
NOTE
27 novembre 2008

10. - NOTE

Tale tesi sperimentale porta in allegato l‟ intero progetto di lavoro sviluppato. La


cartella “FILE SORGENTI” contiene tutte le risorse necessarie per avviare
l‟ applicativo del GUI EDITOR implementato.

Nella sottocartella “Debug” occorre avviare il file eseguibile “Rodgers_i385


GUI.exe”

Oppure è possibile ricompilare l‟ intero progetto aprendo con l‟ amiente di


svuluppo Visual C++ 6.0 il file Rodgers_i385_GUI.dsw (workspace) (dalla
cartella principale).

132
27 novembre 2008

133