sviluppo in c++ di una interfaccia utente per l` editing dei

Transcript

sviluppo in c++ di una interfaccia utente per l` editing dei
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:
Samuele PACIONI
matr. 1005693
Relatore:
Prof. Ing. Aldo Franco
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
………………………………………………………………
3. - PANORAMICA SUL PROTOCOLLO MIDI
14
………………………….. 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
5.2.1 – DESCRIZIONE DELLA FUNZIONE: MODIFICATAB( )
…………….……….…. 49
…………………..……………. 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
5.3.4 – ELEMENTI GRAFICI
…………………………………………………..………………….. 63
………………………………………………………………..……………… 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
10. - NOTE
…………………………………………………………. 130
……………………………………………………………………. 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 dell‟ 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 (elettrodomestici, 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
WM_CHAR
WM_COMMAND
WM_CREATE
WM_DESTROY
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_MOUSEMOVE
WM_PAINT
M_QUIT
WM_SIZE

Descrizione
Un carattere è inserito da tastiera
L‟ utente seleziona un elemento dal menù o un
controllo invia una notifica alla finestra “parente”
E‟ creata una finestra
E‟ chiusa una finestra
Il tasto sinistro del mouse risulta schiaccciato
Il tasto sinistro del mouse risulta rilasciato
Il puntatore del mouse risulta in movimento
Un finestra deve essere ridisegnata (aggiornata)
L‟ applicazione viene terminata
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
BYTE
DATA
BYTE 1
DATA
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:
F0
SYSEX
INDICI
VOCE
OFFSET
NUM ERO
VA LORI
MODIFICATI
VA LORI
MODIFICATI
CK
F7
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 multitimbrica 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
IDD_ DIALOG_ NOTA
Finestra relat iva all‟ ed iting dei parametri
dei 3 parametri di tipo vettore modificali
tramite l‟ imp lementazione grafica d i una
tastiera virtuale costituita da 128 tasti
musicali.
IDD_ DIALOG_PAR
Finestra relativa a ll‟ editing di 23
parametri indiv iduabili per mezzo d i un
nome ed uno o più valori nu merici
rispettivamente raffigurati tramite un‟
etichetta e uno o più edit-box.
IDD_ DIALOG_SLIDER
Finestra relat iva al dispositivo di
interfaccia di t ipo slider per la modifica del
valore numerico; essa risulta rich iamabile
col pulsante >EDITA< dalle 2 dialog
precedenti.
47
Capitolo 5
27 novembre 2008
IDD_ RODGERS_i385_GUI_ DIALOG
IDD_S ELEZIONE_ VOCI_ MULTIPLE
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
principale dell‟ o rgano liturgico favorendo
l‟ interazione con l‟ utente.
Finestra relativa alla lista di bottoni che
consente una veloce visualizzazione e
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
…
…
CBitmapButton
m_Button_ON1;
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 non
cliccato
Pulsante in fase di
click (schiacciato)
Pulsante rilasciato
(effettuata la
selezione)
Pulsante
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 editbox (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
CString
CString
CString
CString
CString
m_cEdNomeVoce;
m_cEdSysexCode;
m_cEdOrgPart_Exist;
m_cEdControlChange32;
m_cEdControlChange0;
m_cEdProgramChange;
59
Capitolo 5
27 novembre 2008
CString
CString
CString
CString
CString
CString
CString
CString
CString
CString
CString
CString
CString
CString
CString
CString
…
CString
CString
m_cEdVolume;
m_cEdFilter;
m_cEdMicroPanpot;
m_cEdPanpot;
m_cEdVoiceFamily;
m_cEdPoliphonicPriority;
m_cEdEnvAttack;
m_cEdEnvDecay;
m_cEdEnvRelease;
m_cEdEnvDelay;
m_cEdRandomTuneProbability;
m_cEdRandomTuneMaxCents;
m_cEdPitch;
m_cEdPipe;
m_cEdOutch;
m_cEdDummy0;
m_cEdDummy6;
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):
F0
SYSEX
INDICI
VOCE
OFFSET
NUM ERO
VA LORI
MODIFICATI
VA LORI
MODIFICATI
CK
F7
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
…
…
CBitmapButton
m_cNOTA0;
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_
UP
IDB_NOTA_
DOWN
IDB_NOTA_
FOCUS
(bianco)
Tasto
non cliccato
IDB_
DISABLE
(bianco)
Tasto in fase di
click (schiacciato)
Tasto rilasciato
(effettuata la
selezione)
Tasto
disabilitato
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_
BLACK_UP
IDB_NOTA_
BLACK_DOWN
IDB_NOTA_
FOCUS
IDB_NOTA_
BLACK_DISABLE
Tasto
non cliccato
Tasto in fase di
click (schiacciato)
Tasto rilasciato
(effettuata la
selezione)
Tasto
disabilitato
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
COLORREF
COLORREF
CWnd*
CString
long
m_LEDLocation;
m_TextColour;
m_ButtonColour;
m_pParent;
m_ButtonText;
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
identificativo
simile
a
quello
usato
tramite un idoneo codice
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
PARAMETRI
VOCE
EDITING
PARAMETRI
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
MULTITIMBRICITÀ
Definibile anche come politimbricità : si intende la
capacità di generare simultaneamente diverse
timbriche, assegnando a ciascuna di esse un numero
variaile delle voci polifoniche a disposizione.
SEQUENCER
E‟ defininibile come un dispositivo hardaware (ma
oggi è molto utilizzato anche la tipologia software)
che permette di creare e produrre delle sequenze di
segnal idi controllo per comandare uno strumento
elettronico
POLIFONIA
Si intende il numero di note (assegnate a uno o più
timbri) suonabili nello stesso istante. Gli strumenti
moderni hanno molta più polifonia dei sintetizzatori
Vintage raggiungendo anche 128 o più note suonabili
contemporaneamente.
UNITÀ EFFETTI
INTEGRATA (DSP)
CONNESSIONI
AUDIO
CONNESSIONI MIDI
L‟ unità effetti integrata si avvale di un apposito
processore di segnali definito digital signal processing
(DSP) applicando effetti come chorus, delay, pictch,
reverbero sui suoni generati internamente o su fonti
esterne dall‟ ingresso audio (analogico o digitale).
Un synth (sintetizzatore) può possedere diverse
tipologie di connessioni audio: analogiche e digitali.
Ciò
permette
molteplici
caratteristiche
di
collegamento con diversi dispositivi esterni.
Solitamente ogni strumento è dotato di almeno una
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_1Files 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,
NUMBER_OF_BUTTONS_IN_LIST_VIEW );
rect.Height()
/
//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
#define TIMER_ID_FLASH
2
// Timer Ping ID
// 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,
SRCCOPY);
0,
0,
//
// 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]
corrispondente a 0.
}
= midi_voci[param_1]
-
param_3;//Settaggio
del
bit
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 DElenco completo delle voci di resgitro relative al RODGERs i538
STOPS
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
BYTE
0
0
0
0
0
0
0
1
1
1
1
1
1
1
2
2
2
2
2
2
2
3
3
3
3
3
3
3
4
4
4
4
4
4
4
5
5
5
5
5
5
BIT
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
NOME VOCE
unused
16'Principal
16'Flute
8'Principal
8'Voce Umana
8' Gemshorn Celeste II
8' Flute Harmonique
8' Rohrflote
8' Gemshorn
8' Flauto Dolce
8' Flute Celeste
8' Unda Maris II
4' Octave
4' Gedacktflote
2' 2/3 Nasat
2' Superoctave
2' Waldflote
1' 1/3 Quint
Sesquialtera II
1' 3/5 Terz
IV - V Mixture
III Sharf
16' Posaune
8' Trompete
8' Trompette Harmonique
8' Krummhorn
8' French Horn
8' Klarine
Harp
Carillon
Harpsichord
Piano
Great Tremulant
16' Great to Great
4' Great to Great
4' Flauto Dolce
4' Flauto Celeste
spare_
8' Prestant
8' Gedackt
4' Principal
123
APPENDICE D
27 novembre 2008
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
5
6
6
6
6
6
6
6
7
7
7
7
7
7
7
8
8
8
8
8
8
8
9
9
9
9
9
9
9
10
10
10
10
10
10
10
11
11
11
11
11
11
11
12
12
12
12
12
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
4' Koppeflote
2' 2/3 Nasard
2' Oktave
1' 1/3 Spitzquinte
1' Sifflote
III -IV Sharf
16' Dulzian
8' Krummhorn
Harpsichord
Positiv tremulant
positiv Unisson Off
spare_
spare_
16' Bourdon Doux
String
8' Viola Pomposa
8' Viola Celeste
8' Viola Celeste II
8' Muted Viols II
8' Bourdon
8' Flauto Dolce
8' Flute Celeste
8' Flute Celeste II
8' Gamba
8' Echo Gamba
4' Principal
4' Nachthorn
2' 2/3 Nasard
2' Doublette
2' Blockflote
1' 3/5 Tierce
1' Sifflote
Sesquialtera II
IV Plein jeu
III Cymbale
Contre Basson
8' Festival Trumpet
8' Trompette
8' Hautbois
8' Voix Humaine (mf)
8' Voix Humaine (mp)
4' Clairon
Swell Tremulant
16' swell to swell
Swell Unison off
4' swell to swell
spare_
spare_
124
APPENDICE D
27 novembre 2008
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
12
12
13
13
13
13
13
13
13
14
14
14
14
14
14
14
15
15
15
15
15
15
15
16
16
16
16
16
16
16
17
17
17
17
17
17
17
18
18
18
18
18
18
18
19
19
19
19
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
spare_
Pedal Chamade
Choir Chamade
Great Chamade
Swell Chamade
Solo Chamade
spare_
spare_
spare_
16' Contre Erzahler
8' Salicional
8' Viola Celeste
8' Hohflote
8' Echo Celeste II
4' Spitzpincipal
4' Lieblichflote
4' Octave Erzahler
2' 2/3 Nasard
2' Octave
2' Flachflote
1' 1/3 Quintflote
1' Sifflote
Mouted Cornet III
III Mixture
8' Troumpette Harmonique
8' Major Tuba
8' Krummhorn
8' Harpsichord
8' Harp
Choir Tremulant
16' choir tp choir
Choir Unison off
4' choir tp choir
8' Concert Flute
8' Erzhler
8' Erzhler CelesteII
8' Flauto Mirabilis
8' Gross Gamba
8' Gamba Celeste
4' Doppelflute
2' 2/3 Flute twelfth
2' Piccolo
Grand jeu VIII
16' Contre Bombarde
8' Fanfare Trumpet
8' Tube Mirabilis
8' English horn
8' French horn
125
APPENDICE D
27 novembre 2008
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
19
19
19
20
20
20
20
20
20
20
21
21
21
21
21
21
21
22
22
22
22
22
22
22
23
23
23
23
23
23
23
24
24
24
24
24
24
24
25
25
25
25
25
25
25
26
26
26
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
8' Clarinet
4' Clarion Harmonique
Carillon
Solo Tremulant
16' Solo to Solo
Solo Unison Off
4' Solo to Solo
_spare_
_spare_
_spare_
32' Contra Pincipal
32' Contre Bourdon
16' Major Bass
16' Principal
16' Subass
16' Violone
16' Gemshorn
16' Bourdon Doux
16' Erzahler
8' Octave
8' Violoncello
8' Gedackt Pommer
8' Bourdon (sw)
4' Choralbass
4' Gedacktpfeife
2' Kleinflote
IV Mixture
V Harmonics
III Cornet
32' Contre Bombarde
32' Contre Basson
16' Bombarde
16' Pousane (gt)
16' Basson
8' Trompette
Oktave Pousane (gt)
4' Clarion
4' Krummhorn
_spare_
_spare_
_spare_
8' Great to Pedal
4' Great to Pedal
8' swell to Pedal
4' swell to Pedal
8' Choir to Pedal
4' Choir to Pedal
8' Solo to Pedal
126
APPENDICE D
27 novembre 2008
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
209
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
26
26
26
26
27
27
27
27
27
27
27
28
28
28
28
28
28
28
29
29
29
29
29
29
29
30
30
30
30
30
30
30
31
31
31
31
31
31
31
32
32
32
32
32
32
32
33
33
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
2
3
4
5
6
0
1
4' Solo to Pedal
8' Positiv to Pedal
16' Swell to Great
8' Swell to Great
4' Swell to Great
16' Choir to Great
8' Choir to Great
4' Choir to Great
16' Solo to Great
8' Solo to Great
4' Solo to Great
16' Positiv to Great
8' Positiv to Great
16' Swell to Choir
8' Swell to Choir
4' Swell to Choir
16' Solo to Choir
8' Solo to Choir
4' Solo to Choir
Positiv Off Choir
16' Choir to Swell
8' Choir to Swell
4' Choir to Swell
8' Solo to Swell
Positiv Off Swell
8' Positiv to Swell
8' Positiv to Swell
8' Positiv to Solo
Great tuttu on Solo
Pipe Tremulant
_spare_
_spare_
_spare_
All Pipes Off
All Ancillary On
Main Tremulant
Flute Tremulant Full
Great/pedal Ancillary On
Choir Pipes Off
Choir Ancillary On
Main Off
Antiphonal On
Swell Pipes Off
Festival Trumpet FF
Swell Ancillary On
Zimbelstern
spare_
_spare_
127
APPENDICE D
27 novembre 2008
233
234
235
236
237
238
239
240
241
242
243
244
33
33
33
33
33
34
34
34
34
34
34
34
2
3
4
5
6
0
1
2
3
4
5
6
_spare_
_spare_
_spare_
_spare_
_spare_
_spare_
_spare_
_spare_
Test/Tune Mode
_spare_
_spare_
_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