Archivi tag: midi

diversamenteArte

Diversamente Arte (prima parte)

Arte ed Informatica si sono incontrate piú volte dalla nascita di quest’ultima.

L’Informatica ha creato nel tempo strumenti a supporto dell’Arte parlando la lingua dell’Arte (dalla conservazione per via digitale di capolavori alla creazione di nuovi strumenti); ma ha saputo dare all’Arte (o meglio agli artisti) anche nuovi linguaggi (e i conseguenti strumenti).

Molti strumenti sono divenuti di uso quotidiano in molte realtà ove l’Arte é anche industria (si pensi agli strumenti di fotoritocco, di modellazione 3D o per la produzione audio-video); altri sono rimasti pura sperimentazione o passatempo per informatici estrosi (e con molto tempo libero).

Di questa “diversa Arte” o “Arte diversa” vogliamo parlare in questo post.

Avrete certo visto forme di ASCII Art, ossia immagini create in documenti testo da caratteri la cui forma e posizione fanno credere a differenti livelli di tono tanto da illudere a sufficienza l’osservatore. Per lo più realizzate con carattere tipografo a corpo fisso (come nella “old school” in voga nel mondo Amiga) o nelle forme piú estreme con corpo variabile e colori (addirittura video con la AAlib di Linux), queste forme d’arte hanno abbellito, decorato o commentato manuali, programmi e quant’altro.

Da notare che anche gli emoticons noti ai piú nascono come forma minimalista di Ascii Art:

:-)

Su YouTube potreste trovare “composizioni per aghi e carta” (avete letto bene!): c’é chi ha “accordato” la propria stampante a matrice di aghi per eseguire composizioni musicali.

Ci sono artisti che amano creare Photographic Mosaic (o Photomosaic), ossia usare immagini come punti per una immagine piú grande frutto di questa composizione; oppure ce ne sono altri un po’ retro’ che si cimentano nella Pixel Art (puntillismo), ossia disegnano un pixel alla volta, con pazienza infinita.

Esistono programmi che consentono a musicisti di generare suoni o musiche a partire da una immagine, o consentono di imprimere il  volto dell’autore nello spettro audio di una composizione (in modo cioé che uno spettrogramma riproduca una immagine di tale volto: è un vezzo questo che si è concesso I’artista Aphex Twin (al secolo Richard David James).

Molti piú dettagli e molte altri modi di fare arte con i computer possono essere approfonditi cercando il termine “demoscene” su Wikipedia.

E veniamo all’esempio di “diversa arte” di cui vogliamo ampliare la conoscenza.

Non tutti sanno che le motherboard di PC e Server sono dotate di beeper (emettitore acustico tipicamente piezoelettrico). Spesso la sua presenza è rilevabile solo nelle fasi pre-boot, nell’accesso al BIOS, e altre “fasi hardware”.

Per sistemisti (o utenti) UNIX il “beep” è una presenza immanente, sin dai tempi dei terminali “telescriventi”: ma anche tra questi sono pochi a conoscere che il beeper può essere “accordato” ad emettere suono di altezza e lunghezza differenti dal classico “beep” (tipicamente 750Hz per 200msec).

Pochi non vuol dire nessuno: utilizzando il comando beep, sia su sistemi FreeBSD, sia su sistemi Linux (con differenti implementazioni), “diversamente artisti” hanno potuto sequenziare l’emissione sonora e temporale del beeper per eseguire musica, benché monofonica (una sola voce) e monotimbrica (un solo colore).

Tra questi artisti, molti lavorano direttamente sui parametri del comando beep (frequenza in Hz e tempo in msec (o cent sec nel caso FreeBSD).
I piú raffinati tentano un approccio con convertitori da MIDI SMF a sequenza di comandi beep (o sequenza di suoi parametri nella implementazione Linux).

Entrambi gli approcci hanno dei problemi: il primo è certamente un metodo “innaturale” e “complicato”; il secondo si deve scontrare con il limite monofonico (innaturale nelle trascrizioni MIDI di musica) e con i problemi della quantizzazione del tempo che può tradursi in una caotica quantità di esecuzioni di comandi beep (o suoi parametri) per mimare il timing degli eventi MIDI.

Il sistema MIDI si basa infatti sulla successione di eventi note on e note off, nell’ottica di una meccanica key pressed (on) e key released (off): questo metodo é perfetto per “registrare” esattamente l’esecuzione di un brano da parte di un musicista su uno strumento di input MIDI (come una keyboard): la riproduzione sarà esattamente uguale (con precisione molto, molto elevata): in questo é cruciale il riferimento temporale (relativo tra due eventi o assoluto).

Il comando beep non ha un sistema di riferimento temporale: il suono viene emesso nel momento di esecuzione del comando e per il tempo indicato (durata): nella versione Linux in cui si può istruire un solo comando ad eseguire piú note e si può indicare anche una latenza temporale tra due note (pausa), ma sempre in termini di durata.

Per i piú ferrati in musica si riconoscerà in questo un approccio più simile al metodo musicale della divisione del tempo, in cui è fondamentale il concetto di durata (e altezza) della nota.
Vogliamo quindi fornire un nuovo strumento per questa Beep Art (o meglio Beep Music), che sia semplice e piú”musicale” possibile.
Proponiamo di scrivere in un semplice file testo una nota per riga (come un “rullo musicale”), espressa con altezza, durata naturale e modificatori, tre campi separati da carattere colon (:). Questo file testo sarà la nostra partitura che un software (che andremo a costruire) provvederà a convertire in una sequenze di comandi beep.

Esistono sistemi di Music Engraving che si basano su file testo molto semplice (vedi abc),
quindi non si consideri banale questo metodo: solo prototipale.

L’altezza sarà espressa in notazione anglosassone e con estensione come dettata anche dallo standard MIDI dalla MMA (da C-2 a G8, ossia dal Do ben 2 ottave sotto la nota piú bassa del pianoforte, fino a 127 semitoni sopra).
La durata sarà espressa in termini di divisione musicale, esprimendo la componente a denominatore. Come modificatori saranno supportati il punto (singolo, doppio e triplo, e i gruppi (irregolari) espressi da un semplice numero.
Le pause saranno espresse da note con altezza “P”, con durata e modificatori come per le note.

E’ evidente che in questo modo la durata e posizione delle note nel tempo musicale é garantita dalla divisione del tempo tra note e pause (come é nelle notazione classica e come é pure per il comando beep.

A completare la sintassi introduciamo indicazioni sulla divisione con il metadato tsig (indicata in modo canonico con una frazione), ed indicazione sul tempo (velocità di esecuzione), con un numero che esprima i bpm (beat for measure) ossia il numero di pulsazioni (note di lunghezza indicate dal denominatore delle tsig: per un 3/4 una nota di 1/4) al minuto.
Questi parametri altro non fanno che produrre il rapporto tra le durate di note e pause in termini di tempo assoluto (secondi o frazionamenti).

Se volessimo realizzare un metronomo per una divisione 4/4 avremo:

A5:4:
A4:4:
A4:4:
A4:4:

Ma questo andrebbe bene se il generatore di toni fosse di natura impulsiva e le note poste all’inizio dei quarti della misura decadessero in ampiezza prima di esaurire la loro durata (caso tipico di una partitura MIDI per un drum kick).

Questo non é quasi mai valido in generale, e non é assolutamete vero nel caso di beep ché si comporta come un generatore di tono ideale (potendo assumere altezza e durata arbitrari).

Per questo la giusta partitura potrebbe essere:

A5:16:
A4:16:
A4:16:
A4:16:

Dato che questo è poco intuitivo per un musicista, introduciamo un meccanismo di “umanizzazione” indicando nella “partitura” i portamenti “legato” (comportamanto naturale) e “staccato” (meccanismo per emulare suoni di natura impulsiva). Questo sintatticamente verrà collocato all’interno di una riga di commento. La riga di commento potrà essere inoltre utilizzata per indicare l’inizio della “misura” (o battuta). Questo potrà essere d’ausilio nella verifica (anche automatica) della trascrizione.

Come si può intuire trascrivere musica da spartito originale con questa notazione risulta assai facile.

Vedremo nel prossimo post come anche la trasformazione in Beep Music sia altrettanto facile.

(Fine prima parte)

EALogoBlack

Archeologia informatica: Interchange File Format

In questo mondo moderno in cui il numero dei formati file proprietari si moltiplica, fa tenerezza pensare ad un lontano passato (era il 1985) quando un colosso dell’informatica ludica (Electronic Arts) definiva uno standard per un formato file universale, tentando così di frenare quello che già all’epoca era una continua corsa alla Babele dei formati.

L’IFFInterchange File Format

L’intento era quello di definire un modello di file capace di contenere diverse componenti multimediali per i suoi software: immagini, suono, animazioni, test, ecc.

Questo standard non è stato più mantenuto e portato avanti, ma molte sono state le influenze e le similitudini che da questo sono state derivate; infatti pur non avendo avuto un futuro autonomo, lo standard è ancora enormemente diffuso (nei suoi eredi e direttamente).

Strutturalmente il file è costruito sul concetto di chunk, ossia un corpo dati identificato da un tipo (una parola a 32 bit di caratteri alfanumerici) e una dimensione (una seconda parola a 32 bit). Se la prima parola è da coniderarsi come sequenza di 4 caratteri alfanumerici interpretabili umanamente con un simbolo, la seconda parola sono un valore a 32 bit in formato big-endian.

Nel mondo Macintosh quei quattro caratteri sono noti come OSType, una parola a 32 bit che ricorre in molte strutture del sistema operativo e in qualche modo ispirate agli stessi principi del’IFF (difficile dire chi ha ispirato chi, data la quasi contemporaneità della nascita del Macintosh con IFF); nel mondo Windows gli sviluppatori chiamano FourCC questi stessi caratteri alfanumerici distintivi di una informazione.

L’uso dell’ordinamento di bit big-endian deriva dalla costruzione di questo standard su architetture Motorola 68000, il cuore dei sistemi Commodore Amiga e Apple Macintosh per i quali Electonics Arts stava sviluppando diverso software di successo (oltre a giochi, programmi di grafica come Deluxe Paint, e di musica come Deluxe Music Construction Set, ecc).

DMCS fu il primo programma capace di sfruttare la capacità di playback a 4 voci con campionamento 8-bit 22Khz dei sistemi Amiga, portando la tecnologia dei campionamenti alla portata di tutti in un epoca in cui una tecnologia analoga era appannaggio di un dispositivo professionale da circa $1700 (vedi Ensoniq Mirage).

La logica di costruzione del formato assomiglia alla codifica TLV (Type/Lenght/Value) dei protocolli di comunicazione:

  • semplici funzioni di analisi per ricercare componenti
  • elementi facilmente trascurabili durante la lettura
  • ordine di apparizione degli elementi nel file non importante
  • formato binario delle informazioni

La definizione del formato ha una certa ricorsività basata su tre strutture basilari: il ‘FORM’, il ‘LIST’ e il ‘CAT ‘. Tre identificatori di altrettanti chunk contenitori che rappresentano un formato specifico (identificato a sua volta da un altra parola 32-bit sempre simbolica), una lista di formati coordinati e un gruppo di formati non meglio correlati.

Lo standard prevedeva in qualche modo un pubblico registro degli identificatori dei chunk dati al fine di evitare collisioni (Commodore ne tenne uno di tutti i formati introdotti da software per le sue macchine); il registro doveva tener conto anche delle specifiche sul dato, al fine di rendere effettiva l’interoperabilità dei sistemi che adottassero il formato.
I vari chunk “registrati” in realtà spesso incorporavano dati destinati ad architetture specifiche e/o comunque molto legati a software o a sistemi operativi (è il caso di immagini HAM – Hold & Modify, una specifica tecnologia per schede grafiche Amiga): questo è certamente contradditorio rispetto alla possibilità di interscambio, ma di contro la definizione pubblica dei chunk poteva comunque consentire l’implementazione di una qualche forma di traduzione.

In ogni caso interpretare un formato file non significa poter gestire i dati: questo è vero anche nel caso dell’XML, pertanto IFF non si trova da solo in questo !

Una particolare implementazione di IFF che è sopravvissuta al tempo è il formato AIFF (Audio Interchange File Format) di Apple.
Un altro erede diretto del IFF è certamente il RIFF (Resource Interchange File Format) di Microsoft e IBM: RIFF è esattamente un IFF  che usa una endianess little-endian (per processori Intel). E’ il formato dei file AVI e WAV.

Tra le similitudini possiamo invece annoverare:

  • il resource fork dei sistemi Macintosh Classic ha una analoga struttura a chunk e identificazione tramite ID alfanumerici a 32 bit (ma anche alcune differenze)
  • il formato SMF (Standard Midi File, definito dalla MIDI Manufacturers Association) è un IFF mancato; quello che manca è il container FORM. Per il resto rispetta esattamente la stessa filosofia, tant’é che Microsoft ha introdotto il chunk RMID per incapsulare un SMF in un formato RIFF.

Molte idee dell’IFF rimangono ancora oggi in formati come XML (ad esempio la possibilità di saltare intere componenti di informazioni quando non se ne conosce il significato o non si ha modo di interpretarli), così come l’idea di marcare sezioni di informazioni con identificatori di 4 caratteri alfanumerici e lunghezza (vedi estensione ID3v2 al formato MP3).

Benché la sua definizione legata ad architetture a 32 bit ne impedisca l’utilizzo per dimensioni di dati/file superiori ai circa 4GB, la sua meccanica di funzionamento lo colloca ancora ai primi posti nella semplicità d’uso e implementazione.
Il concorrente diretto per gli stesi scopi è certamente l’XML (almeno questa è la vulgata): questo ha il vantaggio della portabilità (come IFF), ma l’implementazione di un buon parser XML non è meno onerosa (anzi!) di un semplice e completo parser IFF. E IFF è più rapidamente interpretabile e compatto nelle dimensioni.

Mi domando perché le buone idee spesso vengono abbandonate a favore di presunte novità, mode, interessi diversi ! Strane domande mi faccio !

core_midi_devel

Core MIDI e il tempo

Probabilmente Core Midi, parte dell’infrastruttura software Core Audio per OSX e iOS, è il software meno documentato da Apple e dal web in generale.
Volendo costruire un mini player MIDI integrato (all’interno di un programma più complesso) ho dovuto accontentarmi di un paio di esempi nella documentazione ADC (PlaySequence e PlaySoftMIDI) e i references dell’API, quasi tutta basata su strutture opache.

Costruire un modello funzionante non è stato molto difficile seguendo il prototipo PlaySenquence, apportando anche qualche modifica (ad esempio rimuovendo l’utilizzo delle classi C++ PublicUtility incluse nel progetto a favore di un paio di funzioni per la gestione del tempo di sistema).

Il problema è nato nel momento in cui ho voluto porre nell’interfaccia l’informazione del tempo corrente del brano in esecuzione con MusicPlayer (elemento dell’API).

Interrompiamo il racconto per una breve digressione sul tema temporizzazioni in ambito musicale/MIDI.

In musica il tempo si esprime tenendo presenti due parametri: la misura (ingl. bar) e la velocità.
Il tempo della misura (ingl. time signature) è un concetto più notazionale che pratico, ma che in sostanza caratterizza la collocazione reciproca delle note sull’asse tempo (e la loro durata) nel metro di riferimento adottato, ossia la misura): è un riferimento relativo capace di esprimere la struttura metrica del brano. La divisione viene indicata con una frazione che esprime quante note di quarto (ingl. quarter note; è l’unità di misura della divisione) compongono una misura (ingl. measure).

La velocità indica quanto veloci si susseguono le note. Nella notazione classica sono i riferimenti a quel “Piano”, “Pianissimo”, “Vivace”,con brio“, ecc. Con riferimento al metronomo e nella musica digitale si utilizza invece come parametro la velocità con cui si susseguono le note di quarto nel tempo, ossia quante note di quarto sono presenti in un minuto (beat per minute = BPM): è una misura assoluta e determina la velocità di esecuzione di un brano, qualsiasi metro si adotti.

Nel file MIDI (SMF = Standard Midi File) questi concetti sono espressi in vari modi. Il tempo della misura ad esempio è collocato con meta eventi nel flusso dei dati, così come la velocità di esecuzione, mentre posizione e durata delle note è espressa come differenziale tra due momenti espressi di una unità di misura estranea alla notazione tradizionale ma che funziona egregiamente come ponte tra questa e le necessità dell’informatica: lo step (o tick o, come lo definisce Core Midi, subbeat).
Lo step è una suddivisione della nota di quarto espressa a partire dal concetto di risoluzione, un concetto estraneo alla notazione classica, ma necessario a rendere la relazione tra il tempo assoluto (in milli o microsencondi, dipendentemente dal timer adottato dal software) e la nota di quarto; più propriamente uno step è la più piccola unità riconoscibile all’interno di una nota di quarto a partire da una risoluzione. Una risoluzione di 960 (quella adottata per esempio da Garage Band) indica che nella nota di quarto sono riconoscibili 960 frazioni di tempo (480 per la nota di ottavo, 240 per la nota di sedicesimo, ecc).
Quindi la risoluzione caratterizza la precisione con cui un software può esprimere le posizioni e le durate delle note (andando ben oltre la notazione tradizionale e consentendo così di esprimere quei discostamenti dalla divisione che caratterizza l’esecuzione umana di un brano). Vedi concetto di quantizzazione/umanizzazione.

E veniamo al problema in Core Midi.

Il discorso che segue fa riferimento all’API a partire da OSX 10.5 (e quindi anche iOS della stessa epoca).
L’API mette a disposizione (per la lettura di un SMF, ma anche per la generazione ex-novo) una struttura opaca MusicSequence che contiene una lista di strutture opache MusicTrack, più un accessorio di strutture e API di gestione (come il MusicEventIterator), il tutto a favore di un altro elemento opaco (MusicPlayer) capace di eseguire un brano espresso mediante un MusicSequence.
La funzione MusicSequenceFileLoad (MusicSequence References) costruisce una sequenza a partire da un SMF; nella MusicSequence le informazioni di cui abbiamo parlato in precedenza (e di cui certamente il file SMF ne ha una rappresentazione) vengono distribuite in un modo particolare e scarsamente documentato. L’unico modo di accedere alle informazioni dovrebbe essere attraverso l’API associata (strutture opache, ricordate?) ma tutto non è ben cordinato, specialmente nella documentazione.

La velocità di esecuzione del brano (ad esempio) è collocata in un dizionario leggibile mediante la funzione MusicSequenceGetInfoDictionary per la chiave “tempo”; le sue variazioni però devono essere rilevate (lo fa ovviamente anche MusicPlayer quando esegue il brano) nella “traccia tempo“, una traccia speciale in cui sono collocati (che lo siano stai nel file SMF o no) tutti i meta eventi che caratterizzazo il tempo.
La traccia tempo è ottenibile mediante la funzione MusicSequenceGetTempoTrack e iterabile mediante MusicEventIterator per leggerne e decodificarne ogni evento (se ad esempio il nostro software deve mostrare il contenuto di una MusicSequence invece di darla in pasto a MusicPlayer). Volendo usare MusicPlayer non saremo costretti a farlo.

Ma tornando al nostro problema di visualizzazione del tempo durante l’esecuzione con MusicPlayer, quello che dovremmo utilizzare è la funzione:

OSStatus MusicSequenceBeatsToBarBeatTime(
MusicSequence inSequence,
MusicTimeStamp inBeats,
UInt32 inSubbeatDivisor,
CABarBeatTime *outBarBeatTime
);

Questa dovrebbe essere intesa per mostrare il tempo (internamente espresso come numero float di note di quarto) nella canonica forma:

Misura:Battuta:Frammento di tempo

Per quanto riguarda il parametro inBeats, questo è facilmente ottenibile mediante MusicPlayerGetTime().
Per quanto riguarda la struttura CABarBeatTime del parametro di uscita outBarBeatTime non abbiamo documentazione; ma basta cercare in AudioToolbox/CoreAudioClock.h (erroneamente chiamato ancora nella documentazione AudioToolbox/CAClock.h ) per ottenere

struct CABarBeatTime {
SInt32 bar;
UInt16 beat;
UInt16 subbeat;
UInt16 subbeatDivisor;
UInt16 reserved;
};
typedef struct CABarBeatTime CABarBeatTime;

Ma per quanto riguarda il parametro inSubbeatDivisor non esiste documentazione.
Dopo varia sperimentazione intuisco che il parametro è in qualche modo associato al concetto di risoluzione. So che il file SMF pone questo valore nell’ultima parola a 16 bit del chunk THdr; ma non trovo nell’API di MusicSequence nulla che mi possa far accedere a questa informazione.
Solo una ricerca nei file AudioToolbox/CoreAudioClock.h mi conferma che il parametro subbeatDivisor è legato alla risoluzione: questo mi convince a cercare informazioni nell’API con una ricerca brutale del termine “risoluzione”.
Rinvengo una costante kSequenceTrackProperty_TimeResolution legata all’API di MusicTrack, e per la precizione alla funzione MusicTrackGetProperty e vengo a scoprire dalla documentazione che la sola traccia tempo detiene il dato di risoluzione del brano, esattamente quanto riportato in THrd.

Bingo ! Questo è il parametro necessario.

Vista la difficoltà nel reperire una informazione così vitale implemento una estensione all’API di MusicSequence (mi pare più appropriato) con il doppio fine di documentare e di semplificare l’utilizzo di questa informazione.

Ecco l’implementazione:

/**
* MusicSequenceGetResolution
*
* @author Andrea Tassotti
*
*/
OSStatus MusicSequenceGetResolution(MusicSequence inSequence, SInt16 *outResolution)
{
MusicTrack tempoTrack;

OSStatus status = MusicSequenceGetTempoTrack(inSequence, &tempoTrack);
if (status != noErr) return status;

UInt32 ioLength = sizeof(SInt16);
return MusicTrackGetProperty (
tempoTrack,
kSequenceTrackProperty_TimeResolution,
outResolution,
&ioLength
);
}

che sarà semplicemente utilizzabile nel seguente modo:

MusicTimeStamp time;
if ( MusicPlayerGetTime (player, &time) != noErr )
[NSException raise:@"getPrerollTime" format:@"Can't get time for player"];
if (time >= sequenceLength)
time = sequenceLength;

CABarBeatTime outBarBeatTime;
SInt16 resolution;

if ( MusicSequenceGetResolution(sequence, &resolution) != noErr )
resolution = 240;

if ( MusicSequenceBeatsToBarBeatTime(sequence, time, (UInt32)resolution, &outBarBeatTime) == noErr )
{
// Get the string representation of the current time (Garage Band style)
[timeTextField setStringValue: [NSString stringWithFormat:@"%04i.%2i.%2i.%03i",
outBarBeatTime.bar,
outBarBeatTime.beat,
outBarBeatTime.subbeat / (resolution/4) + 1, // 16-th
outBarBeatTime.subbeat ]];
}

Ovviamente in un caso reale (come nel mio software), la risoluzione verrà estratta una sola volta dalla traccia tempo.

Spero anche in questo caso di essere stato utile a qualcuno.

Il vice-versa, ovvero l’impostazione di una risoluzione per un file SMF si ottiene con la funzione che crea il file (questo è documentato):

OSStatus MusicSequenceFileCreate (
MusicSequence inSequence,
CFURLRef inFileRef,
MusicSequenceFileTypeID inFileType,
MusicSequenceFileFlags inFlags,
SInt inResolution);
);

Ma questa è una altra storia.