Projecte Proj11

De wikijoan
Salta a la navegació Salta a la cerca

Introducció

La idea és que els nens puguin tocar cançons infantils amb pads que es trepitgen. Faré servir les 10 entrades del Alesis DM5, que es connecten a 10 pads que disposo en forma de rotllana. Aquests 10 pads els construeixo jo en forma rodona i de foam (de colors, que siguin grans).

Es disposen els pads en forma de cercle, i el nen, en trepitjar, està marcant la pulsació de la canço.

El projecte Java és la part interessant de l'experiència. Suposo que vull tocar una cançó com Si n'eren 100 soldats. A la cançó li presuposo un tempo. Al nen se li ha de dir que camini (intentant portar un ritme constant). Amb dos o tres passes ja es pot calcular el tempo que porta el nen, i el tempo de la cançó s'ajusta. Si el nen augmenta el ritme, la cançó haurà d'adaptar-se.

El projecte es pot fer més interessant:

  • tenint una biblioteca de cançons
  • Que hi hagi un pad que permeti canviar el programa (instrument)
  • Es pot fer el típic joc musical de recordar una seqüencia de sons
  • Es pot adaptar el joc a bebés: que no s'hagi de caminar, sinó que es toca amb les mans. Experiències sensorials, descoberta de l'entorn.
  • quan s'acaba la cançó torna a començar, però ara sona una altra pista que afegeix un nou instrument. Cada vegada es van incorporant nous instruments,...
  • es pot fer un piano molt bàsic per ser tocat amb les mans (les 7 notes bàsiques)
  • també si tinc un pad que puc tocar amb el peu (stompbox), puc afegir una part rítmica als diferents projectes (bombo).

Bé, com es veu, la idea dels pads que es trepitgen pot donar molt de si. Hauria de donar lloc a divertides activitats per a nens petits.

Construcció de pads que es trepitgen i per a drum kits

links que donen idees:

instruccions detallades: http://www.spikenzielabs.com/SpikenzieLabs/DrumKitKit.html

Una idea és utilitzar CD's. Una altra idea és utilitzar discs de vinils com a material rígid que transmet les vibracions del piezoelèctric.

Posta a punt del hardware

Ja tinc un prototip de taula de drum kit, i el vull fer sonar a través del fluidsynth abans de fer res amb Java:

$ fluidsynth -a alsa -o audio.alsa.device='plughw:1' -c 2 -z 64 -r 44100 -l /home/joan/soundfonts/AI-APiano02trans.sf2

$ aconnect -x
$ aconnect -i -o
$ aconnect 20:0 129:0
$ aconnect -i -o -l

cliente 20: 'UA-25EX' [tipo=kernel]
    0 'UA-25EX MIDI 1  '
	Conectando con: 20:0, 129:0
	Conectado desde: 20:0
cliente 129: 'FLUID Synth (5637)' [tipo=usuario]
    0 'Synth input port (5637:0)'
	Conectado desde: 20:0

i ja funciona. Però compte amb el volum. No és que soni fluix, sinó que el missatge MIDI que es genera és Note ON (per això el puc escoltar amb un soundfont de piano), però hi ha un altre paràmetre que és la durada, i suposo que és molt curta ja que és un mòdul de percussió. El Note ON d'un piano també s'esvaeix, però amb una durada molt més llarga.

v1. Primera prova

En aquesta primera prova utilitzo el fluidsynt (piano), i vull fer sonar notes de piano.

/usr/src/midishare/src/linux/applications/msconnect/msconnect &
/usr/src/midishare/src/linux/applications/msdisplay/msdisplay &
/usr/src/midishare/src/linux/applications/mscontrol/mscontrol &
/usr/local/bin/fluidsynth -a alsa -m midishare -o audio.alsa.device='plughw:1' -c 2 -z 64 -r 96000 -l  /home/joan/soundfonts/AI-APiano02trans.sf2

/usr/local/bin/msAlsaSeq "ALSA_MS_bridge" -i 20:0

Ho faig sonar. He d'analitzar amb calma el missatge MIDI que es rep (TBD).

Nota. El missatge MIDI que proporciona el ALESIS DM-5 després de fer un trigger és de KeyOn. Envia dos missatges: un de KeyON amb volum variable (depenent de la pressió), i un de keyOn amb volum 0 (equivalent a KeyOff). La durada és 0.

Tipus event: 1 (1=typeKeyOn;)
Canal: 0
Data0: 46 (altura)
Data1: 92 (velocitat)
Data2: 0 (durada)

Tipus event: 1 (1=typeKeyOn)
Canal: 0
Data0: 46 (altura)
Data1: 0 (velocitat)
Data2: 0 (durada)

Amb el fluidsynt això m'ha estat difícil d'apreciar, i millor fer-ho treballant amb el CTK-731 (veure més avall).

Aquests missatges MIDI són correctes per a sons de percussió, però si el que vull és fer sonar un piano, el millor serà canviar programàticament el tipus de missatge.

La performance es molt baixa, però segur que es pot millorar doncs tinc tots els factors en contra:

  • no utilitzo kernel RT (problemes amb JAVA del Jaunty)
  • utilitzo el portàtil DELL Inspiron 6000 (4 anys d'antiguitat, el Eclipse va molt just).
  • utilitzo fluidsynty (sintetitzador software)
  • utilitzo una targeta externa USB (Edirol UA-25EX).
  • utilitzo JAVA

Per contra, el cas ideal seria (coses a tenir en compte i per millorar en el cas que vulgui un sistema molt fiable i poca latència):

  • utilitzar el kernel RT (i no necessàriament de Ubuntu Studio, hi ha altres distros).
  • utilitzar un ordinador nou i amb bastanta RAM i CPU. Per a portàtils, en teoria és millor firewire. Per a desktop, ja que perds la portabilitat, el millor és una targeta PCI.
  • els sintetitzadors hardware sempre aniran més ràpids que els software
  • Utilitzar C++ en comptes de JAVA.

Ara, en comptes de utilitzar fluidsynth com a sintetitzador software, vull escoltar el piano pel CTK-731, i es nota molta millora en el so, fins i tot la latència no és determinant (jo no la noto). Per tant, de tots els factors negatius que hem comentat, el factor coll de botella amb el meu pobre sistema és utilitzar el fluidsynth.

Connecto físicament el MIDI OUT del Edirol al MIDI IN del CTK-731, i connecto l'entrada i la sortida del Edirol a través de MidiShare:

/usr/local/bin/msAlsaSeq "ALSA_MS_bridge" -i 20:0 -o 20:0

Comento en el codi les línies que fan referència al fluidsynth.

En el msconnect, no oblidar-se de connectar el Projecte (Proj11) amb el ALSA_MS_bridge, que ara queda:

Millor fer això per codi:

int ref_alsa_bridge;
if ((ref_alsa_bridge = Midi.GetNamedAppl("ALSA_MS_bridge")) > 0) Midi.Connect (ref_alsa_bridge,this.refnum, 1);
if ((ref_alsa_bridge = Midi.GetNamedAppl("ALSA_MS_bridge")) > 0) Midi.Connect (this.refnum,ref_alsa_bridge, 1);

Veig en aquest tros de codi com intercepto el missatge MIDI que arriba del ALESIS, canvio KeyOn per NoteON, fico durada a 150 (valor de compromís que està bé), i poso el volum al màxim. Al final de tot veig com només envio els missatges amb volum>0, doncs els missatges amb volum=0 eren els que es corresponia a Key On + volum 0 = Key Off.

tros de codi MidiShareClass.java

    public void ReceiveAlarm(int ev) {

       	Midi.SetType(ev, 0); //NoteOn
       	Midi.SetData0(ev, 50); //canvio l'altura
    	if (Midi.GetData1(ev)>0) Midi.SetData1(ev, 127);
    	Midi.SetData2(ev, 150); //durada
       	
       	System.out.println("\n");
    	System.out.println("Tipus event: " + Midi.GetType(ev) + " (0=typeNote; 1=typeKeyOn; 2=typeKeyOff)");
    	System.out.println("Canal: " + Midi.GetChan(ev));
    	System.out.println("Data0: " + Midi.GetData0(ev) + " (altura)");
    	System.out.println("Data1: " + Midi.GetData1(ev) + " (velocitat)");
       	System.out.println("Data2: " + Midi.GetData2(ev) + " (durada)");

    
        switch (Midi.GetType(ev)) {
            case Midi.typeNote :
                System.out.println("MidiShareClass, received typeNote");
                //proj11.paintWorld(String.valueOf(Midi.GetData0(ev)));
                break;
            case Midi.typeKeyOn :
                System.out.println("MidiShareClass, received typeKeyOn");
                //proj1.paintWorld(String.valueOf(Midi.GetData0(ev)));
                break;
            case Midi.typeKeyOff :
                //proj1.paintWorld(String.valueOf(Midi.GetData0(ev)));
                break;
            case Midi.typeKeyPress :
                System.out.println("MidiShareClass, received typeKeyPress");
                break;
            case Midi.typeCtrlChange :
                System.out.println("MidiShareClass, typeCtrlChange");
                break;
            case Midi.typeProgChange :
                System.out.println("MidiShareClass, received typeProgChange");
                break;
            case Midi.typeChanPress :
                System.out.println("MidiShareClass, received typeChanPress");
                break;
            case Midi.typePitchWheel :
                System.out.println("MidiShareClass, received typePitchWheel");
                break;
            case Midi.typeSysEx :
                System.out.println("MidiShareClass, received typeSysEx");
                break;
            default :
                break;
        }
        if (Midi.GetData1(ev)>0) Midi.SendIm(this.refnum, ev);
    }

Molt millor utilitzar un sintetitzador hardware, i així ho hauria de fer fins que no tinc un sistema més potent i fiable.

Resum. Utilitzant fluidsynth:

int ref_fluidsynth;
if ((ref_fluidsynth = Midi.GetNamedAppl("fluidsynth")) > 0) Midi.Connect (this.refnum,ref_fluidsynth, 1);

int ref_alsa_bridge;
if ((ref_alsa_bridge = Midi.GetNamedAppl("ALSA_MS_bridge")) > 0) Midi.Connect (ref_alsa_bridge,this.refnum, 1);

Utilitzant sintetitzador hardware:

int ref_alsa_bridge;
if ((ref_alsa_bridge = Midi.GetNamedAppl("ALSA_MS_bridge")) > 0) Midi.Connect (ref_alsa_bridge,this.refnum, 1);
if ((ref_alsa_bridge = Midi.GetNamedAppl("ALSA_MS_bridge")) > 0) Midi.Connect (this.refnum,ref_alsa_bridge, 1);

creat per Joan Quintana Compte, juliol 2009 Informàtica Musical