Archivi tag: audio

core_midi_devel

Come mostrare il tempo di una MusicSequence come nel display LCD di GarageBand

Con un nostro precedente post abbiamo già accennato a questo problema: ora approfondiamo le motivazioni tecnico/teoriche che sono alla base.

Il formato ha 4 valori:

– la misura (bar)
– la battuta (beat)
– la nota di sedicesimo nella battuta
– sottodivisioni della battuta (subbeatdivision)

Il framefork AudioToolbox (Core Audio) offre alcuni strumenti per gestire la divisione del tempo a
supporto di una MusicSequence: i principali sono le seguenti:

  • MusicTimeStamp
  • CABarBeatTime

Il primo è un valore temporale la cui unità è la misura musicale (bar): quindi posto 1 il tempo di durata di una misura, tutto è multiplo o sottomultiplo di questo: ne consegue che MusicTimeStamp è un valore in virgola mobile con la necessità di una certa precisione.

La seconda è una struttura utilizzata per le conversioni (vedi le funzioni MusicSequenceBeatsToBarBeatTime e MusicSequenceBarBeatTimeToBeats), ma la scarsa documentazione non fornisce quanto serve a che queste funzioni facciano a pieno il loro dovere.

Il lato oscuro di queste funzione è il parametro inSubbeatDivisor (per la funzione MusicSequenceBeatsToBarBeatTime) o il campo subbeatDivisor nella struttura CABarBearTime (da passare alla funzione MusicSequenceBarBeatTimeToBeats).

Nella soluzione proposta nel precedente post utilizzavamo la risoluzione della sequenza (ppq) come parametro, e sembrava funzionare egregiamente: invero su divisioni di tempo differenti avremmo potuto avere problemi di rappresentazione.

Infatti il subbeatDivisor è un valore in relazione non solo alla risoluzione (in ppq), ma anche alla divisione del tempo corrente (time signature) e per la precisione al denominatore della divisione del tempo, secondo la sequente relazione:

subbeatDivisor = ( (ppq >> 2) << sig_denominator )

dove sig_denominator è espresso come l’esponente di una potenza di 2 che determina il denominatore della divisione temporale corrente. Una breve nota: il memorizzare l’esponente è un meccanismo utilizzato anche nel meta evento di una SMF o di una MusicTrack: la Tempo Track di una MusicSequence è una MusicTrack, pertanto la divisione è registrata in questa mediante meta eventi (di tipo kMIDIMetaEvent_Time_Signature).

La risoluzione è espressa in parti (tick o pulse) di una nota di quarto (ppq o ppqn), ma quando cambia il denominatore della divisione temporale, allora per avere medesima “precisione” occorre ampliare o ridurre questo valore quando esprimiamo una posizione nel tempo al fine di consentire di avere lo stesso numero di parti nel beat (che ha cambiato dimensione per il diverso denominatore della divizione del tempo).

Dato la divisione di 6/8 e una risoluzinone di 240 ppq:

UInt8    tsig_num = 6;
UInt8    tsig_den = 3;        // 2^3 = 8
UInt16    resolution = 240;    // PPQ

allora avremo:

UInt16  subbeatDivisor = ( (resolution >> 2) << tsig_den );

Le dimensioni delle variabili sono conformi a quanto atteso dalle strutture o funzioni in AudioToolbox.

Il penultimo valore da mostrare è il numero della nota di sedicesimo corrente, e come abbiamo visto l’altra volta è ottenibile mediante la seguente:

subbeat / (subbeatDivisor / 4) + 1

dove subbeat rappresente il “pulse” corrente di una nota di quarto, quindi rapportanto alla divisione corrente (subbeatDivisore) se ne prende la quarta parte: 4 * 4 = 16 !

Per eseguire qualche esperimento ecco come scrivere un beat di tanti eventi quanti i tick indicati dalla risoluzione prescelta.

MusicTrack outTrack;
UInt8    tsig_num = 6;
UInt8    tsig_den = 3;
UInt16    resolution = 240;    // PPQ
UInt16  subbeatDivisor = ( (resolution >> 2) << tsig_den );
CABarBeatTime inBarBeatTime;
MIDINoteMessage aNoteMessage;
MusicTimeStamp       outBeats ;

MusicSequenceNewTrack (mainSequence, &outTrack);

aNoteMessage.channel = 1;
aNoteMessage.note = 23 & 0x0f;
aNoteMessage.velocity = 80 & 0x0f;
aNoteMessage.releaseVelocity = 0;
aNoteMessage.duration = 1/960;

for(int i = 0; i < resolution; i++){
inBarBeatTime.bar = 1;
inBarBeatTime.beat = 1;
inBarBeatTime.subbeat = i;
inBarBeatTime.subbeatDivisor = subbeatDivisor;

MusicSequenceBarBeatTimeToBeats(mainSequence, &inBarBeatTime, &outBeats);
MusicTrackNewMIDINoteEvent (outTrack, outBeats, &aNoteMessage);
}

Ovviamente non abbiamo detto della cosa più importante: come leggere il denominatore della divisione in relazione al tempo corrente di riproduzione (o visualizzazione).

Questo sarà oggetto di un altro post che introdurrà la descrizione di un mio progetto di ampliamento del framework AudioToolkit che presto pubblicherò su github.

Per ora basta.

osxbeep

Beep OS X, Beep!

Nell’implementazione dello strato BSD, OSX omette alcuni comandi; poco male se una alternativa è data da un comando nativo: verosimilmente l’astrazione BSD non era in grado di realizzare a pieno il compito. Ma questo non é evidentemente l’unico motivo.

Tra i vari “ports” BSD, Apple ne seleziona solo alcuni, mantenendoli spesso ad una versione “vecchia” (vedi il caso di bash, ancora rimasta alla 3).

Non dovrebbe dunque sorprendere l’assenza del port del comando beep, sebbene sia difficilmente spiegabile in termini tecnologici; al piú si spiega in termini di conformità alle metafore della interfaccia che prevedono altro per la segnalazione di eventi ad utente.

L’ironia del caso vuole che mentre il mondo Linux evolve la sua implementazione del comando beep, anche il port per FreeBSD è stato rimosso in quanto obsoleto, alla buona faccia di chi voglia ancora utilizzarlo.
Ovviamente il nostro interesse per il comando beep nel mondo OS X è indotto dalle cose espresse nei nostri precedenti articoli, ma andiamo per gradi.
Ricercando nella documentazione di sviluppo si trova la disponibilità della funzione beep() nella libreria ncurses (https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/beep.3x.html): questa peró esegue il suono di avviso configurato negli effetti sonori nelle preferenze di sistema.
Quindi, almeno per conformità alle metafore dell’interfaccia, il comando beep poteva essere implementato semplicemente utilizzando questa funzione di ncurses.

Ricercando in Internet (come è nostro solito) una soluzione per implementare un beep su OS X troviamo tante risposte ovvie, ma non quella che cercavamo (ovvio anche questo!)

E’ ovvio che un comando echo (o print) in shell riproduca con un suono il carattere audible alert (\a=ASCII 0x7, carattere di controllo
che deve i suoi natali alla Teletype Model 33 ASR):

echo -e "\a"

ma é anche ovvio che si comporti come prevede l’implementazione della libreria ncurses, come per l’equivalente:

tput bel

con cui si attiva la capability del terminale (che dipendono dalla solita libreria)

Ovvio (benchè meno diretto) la possibilitá di eseguire un beep come istruzione AppleScript:

osascript -e beep

e non ci si può stupire se anche questo metodo (piú che mai OS X) esegue Il suono di sistema previsto per gli avvisi.

Il suggerimento piú esilarante è certamente il seguente:

say beep

benchè abbia un suo fascino.
Dunque è giunto il momento di trovare una risposta in stile Nerdammer e dotare il nostro OS X del comando beep.
Volevamo scegliere come modello la piú evoluta implementazione Linux (di Johnathan Nightingale) invece di quella del port FreeBSD:
questioni pratiche e di tempo ci impongono al momento di implementare la versione FreeBSD: ritorneremo sulla implementazione per evolverla accessivamente.

Questa scelta ci consentirà comunque di utilizzare le nostre “beepsongs” come prodotte dal software descritto nel
precedente articolo (ponendo in modo FreeBSD l’output dello script). Alla fine in realtà è questo che cercavamo!

Per realizzare il nostro progetto ci avvaliamo del framework Core Audio, ed in particolare utilizziamo una Audio Unit di tipo output con definita una funzione callback per il rendering del buffer audio, il che ci consentirà di definire algoritmicamente (dunque dinamicamente) la forma d’onda emessa.

Vogliamo con questo simulare al meglio il circuito analogico del beeper delle schede madri di pc e server, evitando i limiti e la complessità che altri metodi imporrebbero volendo ottenere campo di frequenze e durata di emissione molto ampi.

Come al solito la nostra implementazione é una guida: ci si perdoni quindi l’assenza di ricerca di ottimizzazioni nelle prestazioni (ad esempio l’algoritmo di generazione dell’onda sinusoidale non é il piú efficiente in assoluto).

Potete scaricare il codice sorgente da Git Hub e compilarlo sul vostro OS X come indicato nella documentazione.

Ancora una volta buon ascolto!

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 !

articolo_itunes

Ancora su iTunes e playlist

Con l’ultimo post su iTunes ho potuto riabbracciare la programmazione AppleScript che avevo tralasciato per lunghi anni, da quando lavoravo ancora con un OS Classic 7.5.5 !

Ovviamente ci ho ripreso gusto, pertanto eccomi di nuovo con un altro post che prosegue in qualche modo il precedente.

L’idea di questa nuova estensione alle funzionalità di iTunes mi viene dal passato, ossia da quei lettori di CD Audio che erano parte degli impianti Hi-Fi degli anni 90 e che oggi sono solo appannaggio di impianti detti di “Hi-Fi esoterico“, dove un componente di tal genere può costare anche fino e oltre i 1000€! Oggi che il mondo musicale è sempre più liquido, un lettore CD Audio è qualcosa rara, pertanto per molti sono solo un ricordo.

In ogni caso quei dispositivi avevano una funzione (almeno quelli di una certa fascia) interessante che non si è diffusa nel mondo liquido. La scansione rapida delle tracce.

La scansione prevedeva l’ascolto dei primi 10 secondi di ogni traccia del disco.

Ebbene abbiamo implementato due script per iTunes che mimano questa funzione sulla playlist selezionata.

Il primo è esattamente a scansione dall’inizione di ogni traccia della playlist selezionata; il secondo invece è una variante che mi è utile nella costruzione di playlist per sonorizzazioni: consente l’ascolto degli ultimi 10 secondi di ciascuna traccia della playlist. Questa funzione è molto utile per trovare i migliori collegamenti tra fine e inizio di tracce che devono susseguirsi in un mix continuativo.

Rammentiamo (cosa non fatta nell’altro post) che per integrare i nostri AppleScript in iTunes sarà sufficiente collocarli in /Library/iTunes/Scripts.

Ovviamente anche in questo caso gli script sono un abbozzo funzionante che può essere migliorato a vostro piacere.

--
-- Scan mode 1
--
--	Head of track for 10 seconds
--
property thePlaylist : ""
property scanTime : 10

tell application "iTunes"
	-- Per le sorgentti che non sono una playlist (come Film, ecc)
	try
		set thePlaylist to (view of front window)
	on error number errn
	end try

	if thePlaylist ≠ "" then
		repeat with theTrack in (tracks of thePlaylist)
			play theTrack
			repeat while player position < scanTime
				delay 0.2
			end repeat
		end repeat
	end if
end tell
--
-- Scan mode 2
--
--	Tail of track for 10 seconds
--
property thePlaylist : ""
property scanTime : 10

tell application "iTunes"
	-- Per le sorgentti che non sono una playlist (come Film, ecc)
	try
		set thePlaylist to (view of front window)
	on error number errn
	end try

	if thePlaylist ≠ "" then
		repeat with theTrack in (tracks of thePlaylist)
			play theTrack
			set player position to (duration of theTrack) - scanTime
			repeat while player position < (duration of theTrack) - 1
				delay 0.2
			end repeat
			pause
		end repeat
	end if
end tell
articolo_itunes

Esportare una playlist iTunes su chiavetta USB

Per tutti coloro che utilizzano al meglio (e felicemente) iTunes e la sua libreria organizzata e consolidata, è difficile pensare ad una organizzazione del materiale audio senza iTunes.

Molti però tendono ancora a gestire i file multimediali in maniera autonoma, specie chi di questa gestione automatizzata, comoda ed integrata non ha mai sentito parlare (non è nel loro DNA, diciamo). Va bé! ci sono forme alternative di pensiero che dicono che noi utenti Apple invero siamo indottrinati; fate come volete. Tant’é. Noi viviamo sereni.

Però il problema nasce quando occorre integrarsi con il mondo a “gestione manuale”.
Se qualcuno ci chiede una copia della nostra playlist (per ascoltare le nostre canzoni autoprodotte rigorosamente con il nostro GarageBand !!! ovviamente !!! ;-), potrebbe essere difficile raccogliere in giro per la cartella “iTunes Music” tutti i file e copiarli diciamo su una chiavetta USB.

Ecco che ci viene incontro un piccolo frammento di codice AppleScript da me creato in pochi minuti (potenza del linguaggio):

tell application "iTunes"
    repeat with aTrack in (tracks of user playlist "Prova")
        set theAlias to (get location of aTrack)
        set theAlbum to (get album of aTrack).
        tell application "Finder"
        try
                duplicate theAlias to folder "Macintosh HD:Users:andrea:Desktop:Prova"
        on error number errn
            if errn = -15267 then
                make new folder at folder "Macintosh HD:Users:andrea:Desktop:Prova" with properties {name:theAlbum}
                duplicate theAlias to folder ("Macintosh HD:Users:andrea:Desktop:Prova:" & theAlbum)
            end if
        end try
        end tell
    end repeat
end tell

Rozzamente (non abbiamo prodotto una interfaccia per richiedere sorgente, ossia playlist, e destinazione, ossia un folder) ma semplicemente questo script cercherà per noi tutti gli originali indicati da una playlist e li copierà in un folder da noi indicato: qualora il file dovesse collidere con uno già presente (ricordiamo che i nomi di file gestiti con libreria organizzata da iTunes sono fatti del numero di traccia e del titolo, quindi possono sussistere casi di omonimia in assenza di album) allora crea un subfolder con il titolo dell’album.

Potrete modificarlo a piacimento, magari creando direttamente la gerarchia di folder che più vi aggrada, introducendo altre meta informazioni, se necessario.

Buon ascolto!