Ubuntu Studio: Resum preparació Ubuntu Studio amb MidiShare

De Wikijoan
Dreceres ràpides: navegació, cerca

Contingut

Passos inicials

Aquest document està realitzat per a Ubuntu Studio 7.10

Ara que ja hem resol la instal.lació de MidiShare a Ubuntu Studio (7.10), anem a fer un resum de què he de fer a la màquina per començar a treballar.

$ sudo apt-get install sun-java6-bin
$ sudo apt-get install sun-java6-jre (de fet, ja queda instal.lat amb l'anterior pas)
$ sudo apt-get install sun-java6-jdk

s'instal.la a /usr/bin

$ java -version

export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.03
export PATH=$JAVA_HOME/bin:$PATH

-> s'han de fer els canvis permanents

$ joe /home/joan/.bashrc -> i ficar al final aquestes dues línies (comprovar en un reinici que els canvis són permanents)
$ sudo apt-get install eclipse


Compilació MidiShare

Compilació_MidiShare:_síntesi

Començant a treballar amb MidiShare (vull escoltar alguna cosa)

Un cop compilat el MidiShare, reinicio

faig lsmod i tinc el mòdul 'midishare' -> motiu: no he arrencat amb el kernel rt (uname -r). Per escollir el kernel d'arrencada, clicar ESC en l'inici. Mirar com fer que el kernel rt sigui per defecte

[per enviar els errors d'una comanda a fitxer: $ comanda 2> error.log]

a /midishare/src/tools hi ha unes quantes aplicacions en C que s'han de compilar i que serveixen per veure informació de si està funcionant el MidiShare.

tot sembla que està funcionant correctament, però no sento res.

Compilació de les aplicacions C

quan poso OK vol dir que s'ha compilat correctament.

./TDrivers: MidiShare drivers test.

per ex,

Connections :
    MidiConnect drivers : OK
    WakeUp MidiShare...
    MidiConnect drivers : OK
    MidiConnect drivers to appl : OK
    MidiConnect appl to driver : OK

Slots management :
    MidiAddSlot : (7e , 1007e) OK
    MidiGetIndSlot : 7e OK
    ..MidiGetSlotInfos : 
      1 : " o���        �������" direction: output slot -> cooregir aquests caràcters
      2 : " o���        �������" direction: output slot
    MidiSetSlotName : " o���    �������" OK

Warning : new name not correctly set : " o���   �������" instead "New Name"
    MidiConnectSlot : OK
    MidiIsSlotConnected : OK
Warning : MidiGetSlotInfos slot not connected
    disconnect...
    MidiRemoveSlot : OK

./TEvents: Allocation, emission and reception of MidiShare events. -> OK, però se suposa que hauríem d'escoltar alguna cosa

./TFilters: MidiShare filters tests. Tot OK

./TOutEvents: MidiShare drivers transmission and reception tests -> hi ha warnings

./TFonctions: es penja?

la carpeta /src/win-mono està pensada per a projectes escrits amb VC (Visual C), i que es poden importar a Linux gràcies al projecte Mono

compilo els fitxers que hi ha a:

/src/common/atomic/benchs$

./ffbench: programació per fils

dins de /lib/Network hi ha tot el tema de xarxa, que de moment no ho toco.

Jugant amb msconnect

Començo a jugar amb l'aplicació msconnect: Experiment que funciona:

miniatura

Tinc les tres aplicacions clients engegades. A msconnect connecto com a Aplicació: mscontrol amb Destinació: msdiplay. Aleshores quan clico sobre els botons de mscontrol veig com van arribant els missatges. Tot està bé excepte de què no escolto res. Em falta la última part: com connecto el meu driver midishare amb la meva targeta de so (interna).

És el moment d'enviar un mail al forum de MidiShare:

OK, ja tinc un sistema amb MidiShare instal.lat correctament a Ubuntu Studio (ja vaig resoldre el meu problema amb la llibreria JMusic), i totes les aplicacions C i Java funcionant (msconnect, msdisplay, mscontrol, TutorialPart1.java,...). Tot sembla perfecte excepte que encara no he escoltat res...
Suposo que el que em falta és connectar el driver midishare (suposo que funciona com a dispositiu-interface lògica) amb una tarja de so real (de moment la tarja de so interna)

Algunes pistes
-puc escoltar un fitxer midi amb el Rosegarden i un fitxer wav
-lsmod: apareix midishare
-/dev/midi: no existeix. Crec que hauria d'aparèixer
-fluidsynth -a jack -m midishare Musica_Theoria.sf2 -> error: Couldn't find the requested midi driver Failed to create the MIDI thread; no MIDI input will be available.

D'altra banda hi ha una cosa que no entenc. Veig paral.lelismes entre msdrivers (a Windows) i msconnect (a Linux). msdrivers no existeix a Linux. A msdrivers de Windows connectava slots (podia connectar un controlador MIDI amb la meva tarja de so física, a través d'un port). A Linux el concepte de port no el veig per enlloc, i a Destination i Source puc connectar aplicacions client, però no dispositius físics).

Puc veure la meva tarja de so de dues maneres:

$ lspci -> tot el que hi ha connectat al port PCI
00:1e.2 Multimedia audio controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (rev 03)

$ cat /proc/asound/cards -> list of sound cards
 0 [ICH6           ]: ICH4 - Intel ICH6
                      Intel ICH6 with STAC9752,53 at irq 16

Què és el que em falta??
Gràcies

el text original enviat, en anglès:

OK, I have my MidiShare-Ubuntu Studio system working correctly (I already solved my shared library JMusic problem), and all the C and Java appls are working (msconnect, msdisplay, mscontrol, TutorialPart1.java,...). Everyting seems perfect apart from that I can't hear anything (midishare talking, of course, my speakers are on).
I think that the problem is that the midishare driver (it's a logical interface/device, isn't it?) must be connected with a real soundcard (at the moment it's the internal one, an external Edirol in the future).

Some clues:
-I can hear a midi file with Rosegarden and a wav file
-lsmod: appears midishare
-/dev/midi: doesn't exist. It Must exist, I think...
-fluidsynth -a jack -m midishare Musica_Theoria.sf2 -> error: Couldn't find the requested midi driver. Failed to create the MIDI thread; no MIDI input
will be available.

On the other hand, there is a thing I don't understand. I see similarities between msdrivers (in Windows) and msconnect (in Linux). msdrivers doesn't exist in Linux. msdrivers in Windows connects slots (for instance, a MIDI controller with a soundcard, through a port in the 256 matrix ports). In Linux I can't see anywhere the port concept, and in Destination and Source I can connect client applications, but not phisical devices).

I can see my soundcard in two ways:

$ lspci -> everything connected in my PCI port
00:1e.2 Multimedia audio controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (rev 03)

$ cat /proc/asound/cards -> list of sound cards
 0 [ICH6           ]: ICH4 - Intel ICH6
                      Intel ICH6 with STAC9752,53 at irq 16

What's wrong??

Thanks,
Joan Quintana

Resposta que obtinc:

Hi Joan,

On Linux, MidiShare relies on ALSA for the MIDI Drivers. You can use
Albert Graef's msAlsaSeq (in src/linux/drivers/alsa/) to create a bridge
between MidiShare and Alsa. Look at the included man pages for detailed
instructions.

Cheers

Yann

Investigo:

si executo el binari msAlsaSeq, funciona (MidiShare ALSA driver anchored on "MidiShare/ALSA Bridge" is running.Type 'q' to quit.).

Si ara obro el msconnect veig que 'Midishare/ALSA Bridge' és una aplicació, i també és source i Destination. Obro també el msdisplay i el mscontrol, jugo amb moltes possibilitats, i no hi ha manera de què soni res

http://www.krugle.org/examples/p-oS4uTImHfLz27oCg/README: -> llegir tot l'article

Finally, to actually get some sound you need to run a driver which you can connect your Q-Midi and other MidiShare applications to. (This can also be taken care of by running the midicc application described at the end of this file.) Various drivers are distributed with MidiShare. Unless you really need to use OSS, we recommend going with the new MidiShare/ALSA driver, msAlsaSeq, which is included in all recent MidiShare versions; this driver is also included in the latest versions of the MidiShare rpms provided on the Q homepage. It allows you to connect your MidiShare applications to arbitrary ALSA devices and other ALSA sequencer clients, and to map the ALSA client ports to corresponding MidiShare ports; see the msAlsaSeq(1) man page for details.

fixem-nos en la línia "and to map the ALSA client ports to corresponding MidiShare ports". Jo crec que això és el que passa, doncs en definitiva el problema que tenia en Windows (amb el que em vaig barallar fins que vaig aconseguir sentir alguna cosa) és que no tenia ben mapejat els ports.

...These routines are also used to connect a client to physical MIDI devices. Under OS X and Windows, it is sufficient to connect with client #0 (the predefined "MidiShare" client) which manages the MIDI I/O drivers according to the port definitions specified with the msDrivers application. Under Linux, drivers are currently implemented as ordinary clients, such as the msAlsaSeq and msRawMidi drivers distributed with the Linux version of MidiShare. Here you have to connect directly with the MIDI driver client which you want to use...

$ msAlsaSeq -h
Usage: msAlsaSeq [client-name] [-i id:port[/msport] | -o id:port[/msport] ...] -> aquí veig el tema dels ports
$ msAlsaSeq mscontrol -i 0:0/0 -o 0:0/0 
Connecting input "System" (0:0) to MidiShare port 0.
Connecting output "System" (0:0) to MidiShare port 0.
MidiShare ALSA driver anchored on "mscontrol" is running.
Type 'q' to quit.

faig man msAlsaSeq i no surt res

ara bé, si fem

midishare/src/linux/drivers/alsa$ make -n

veig que s'instal.len els manuals a MAN1=/usr/local/man/man1, i efectivament, en aquest directori hi ha msAlsaSeq.1.bz2

en el directori alsa recompilo i instal.lo (no ho havia fet?)

$ sudo make install
install -m 6755 -s msAlsaSeq /usr/local/bin
[ -f msAlsaSeq.1.bz2 ] || bzip2 msAlsaSeq.1
install -d /usr/local/man/man1
install -m 644 -o root msAlsaSeq.1.bz2 /usr/local/man/man1

per descomprimir un arxiu bz2:

$ bunzip2 msAlsaSeq.1.bz2

i es crea el fitxer msAlsaSeq.1, que efectivament és una man page:

$ man msAlsaSeq

creo les altres man pages:

$ bunzip2 MidiConnect.1.bz2
$ bunzip2 MidiCountAppls.1.bz2
$ bunzip2 MidiGetIndAppl.1.bz2
$ bunzip2 MidiGetName.1.bz2
$ bunzip2 MidiGetNamedAppl.1.bz2
$ bunzip2 MidiGetStat.1.bz2
$ bunzip2 MidiGetTime.1.bz2
$ bunzip2 MidiGetVersion.1.bz2
$ bunzip2 MidiIsConnected.1.bz2
$ bunzip2 msInetDriver.1.bz2
$ bunzip2 msQuit.1.bz2

Més coses: quan em connecto al msAlsaSeq (MidiShare ALSA driver anchored on "MidiShare/ALSA Bridge" is running.), i vaig al JACK Audio Connection KIT, dins del botó Connect-pestanya MIDI puc veure MidiShare/ALSA Bridge tant com a Readable Client/Output Port com a Writable Client/Input Port -> vaig pel bon camí, però encara no puc fer res.

Important!

$ timidity 158.mid

executo en mode comanda i comença el fitxer. Timidity representa la intefície MIDI de la meva targeta de so interna. Per tant, hauré de connectar el driver de MidiShare amb el Timidity. Això ho puc fer amb el Jack Audio Control Kit, o amb el msconnect. Amb el Jack Audio Control Kit puc veure per quin port treballa la meva targeta de so (el TiMidity):

128:TiMidity -> 128 és le referència del client (veure més avall, comanda aconnect)

	0:TiMidit port 0
	1:TiMidit port 1
	2:TiMidit port 2
	3:TiMidit port 3
$ timidity -h

-> hi ha moltes opcions

Usage: msAlsaSeq [client-name] [-i id:port[/msport] | -o id:port[/msport] ...]

-> aquí veig el tema dels ports

$ msAlsaSeq -i 64:0 -o 64:0

connects input and output to port 0 of client 64. Usually this corresponds to the external MIDI interface of your first soundcard. To find out about the available ALSA sequencer clients and ports on your system, run the ALSA program aconnect with the -i and -o options. You can also use the MidiShare msconnect program to connect your MidiShare applications with the MidiShare client created by msAlsaSeq.

$aconnect -i -o
client 0: 'System' [type=kernel]
    0 'Timer           '
    1 'Announce        '
client 14: 'Midi Through' [type=kernel]
    0 'Midi Through Port-0'
client 128: 'TiMidity' [type=user]
    0 'TiMidity port 0 '
    1 'TiMidity port 1 '
    2 'TiMidity port 2 '
    3 'TiMidity port 3 '

Ara bé, si engego el msAlsaSeq (sense cap opció), s'afegeix lògicament un altre client a la llista:

client 130: 'MidiShare/ALSA Bridge' [type=user]
    0 'MidiShare/ALSA Bridge'


ja ho tinc !!!!!!!:

el client 128 és el timidity (targeta de so) i el client 130 és el MidiShare/ALSA Bridge. Ara que ja sé els clients que he de connectar, engego el driver:

$ msAlsaSeq -i 130:0 -o 128:0

ens connectem pel port 0. Això seria l'equivalent del msdrivers del Windows.

Ara engego el mscontrol i el msconnect:

En el msconnect ho associo de la següent manera:

Jugo amb el mscontrol i sona.

Veig que estan activats tots els ports i tots els canals

Tot això sense tenir el servidor jack en funcionament

msAlsaSeq -i 130:1 -o 128:1 -> també funciona
msAlsaSeq -i 130:2 -o 128:2 -> no funciona
msAlsaSeq -i 130:3 -o 128:3 -> no funciona
msAlsaSeq -i 130:2 -o 128:0 a msAlsaSeq -i 130:127 -o 128:0  -> funciona
msAlsaSeq -i 130:0 -o 128:2 -> no funciona

Conclusió: per al client 128 (timidity) només funciona el port 0 i el 1, i per al 130 funcionen tots els ports. D'altra banda, en el mscontrol puc jugar amb el slider 'ports' i això no afecta res, continua sonant.

ja funciona el fluidsynth amb el midishare: (no sé què fer amb això però almenys no em dóna error)

$ fluidsynth -m midishare -a jack /home/joan/fluidsynth/doc/example.sf2

Created project project-1 in directory /home/joan/audio-projects/project-1
Added client cdd5bfed-bd22-4d29-9cc0-9bcdedd03ba7 of class fluidsynth to project project-1
lash_init: Not attempting to start daemon server automatically
JACK tmpdir identified as [/dev/shm]
FluidSynth version 1.0.8
Copyright (C) 2000-2006 Peter Hanappe and others.
Distributed under the LGPL license.
SoundFont(R) is a registered trademark of E-mu Systems, Inc.

Type 'help' for information on commands and 'help help' for help topics.

instal.lació fluidsynth amb compatibilitat midishare

$ sudo apt-get install build-essential automake libtool 
$ sudo apt-get install subversion
$ sudo apt-get install libasound2-dev 
$ sudo apt-get install libjack-dev
$ sudo apt-get install lashd lash-bin liblash-dev  

$ svn co https://resonance.org/svn/fluidsynth/trunk/fluidsynth
$ cd fluidsynth
$ ./autogen.sh -> es crea configure
$ ./configure --enable-midishare -> OK
$ make 
$ sudo make install

OK

$ fluidsynth -m alsa_seq /home/joan/fluidsynth/doc/example.sf2

-> funciona, el que no funciona és -m midishare. ja s'ha solucionat després de barallar-me amb el driver msAlsaSeq

Utilització d'un sintetitzador MIDI: fluidsynth

la idea és que la sortida MIDI sigui redirigida al fluidsynth, que pot fer síntesi de so si li carregues el soundfont corresponent.

Recordem que hem compilat el fluidsynth amb l'opció 'midishare enabled' (veure how to)

$ fluidsynth -a jack -m midishare /home/joan/fluidsynth/sf2/VintageDreamsWaves-v2.sf2

-> es posa a funcionar i no dóna cap missatge d'error.

$ msconnect

-> veig el fluidsynth com a aplicació client de midishare, i per tant puc redirigir la sortida de les meves aplicacions al fluidsynth

Instal.lació de la JMusic shared library de MidiShare (libJMidi.so.1)

En aquest link està explicat totes les proves que he fet per compilar i executar correctament els primers exemples de MidiShare i Java (/usr/src/midishare/lang/java/native). Els problemes venien bàsicament per com dir-li a un projecte Java que utilitzi la shared library JMusic, que forma part del cor de MidiShare (Linux version of midishare consists of both a shared library -JMusic-, and a kernel module -es comprova amb lsmod).

Utilitzant msdisplay en el codi Java puc veure i analitzar el correcte funcionament de les aplicacions. Però ara em falta el més important, que és aconseguir que les aplicacions sonin per la targeta de so. I això és el que s'explica a continuació.

programant MidiShare amb JAVA

Nota: aquest document s'ha d'actualitzar per tal de fer sonar els exemples amb la targeta de so Edirol UA-25EX

$ export CLASSPATH=/usr/src/midishare/lang/java/native

S'han de fer els canvis permanents:

$ joe /home/joan/.bashrc

-> ficar al final la línia CLASSPATH=/usr/src/midishare/lang/java/native

en ppi no cal recompilar grame.midishare.midi

l -> hi ha un makefile abans de compilar, A la pàgina web de Java em descarrego JDK 6 Update 7 (jdk-6u7-linux-i586.bin, 74Mb)

$ sudo apt-get install java-package

A la pàgina web de Java em descarrego JDK 6 Update 7 (jdk-6u7-linux-i586.bin, 74Mb)

$ fakeroot make-jpkg jdk-6u7-linux-i586.bin

-> el que fa això és construir un paquet debian a partir de les fonts: sun-j2sdk1.6_1.6.0+update7_i386.deb

$ sudo dpkg -i sun-j2sdk1.6_1.6.0+update7_i386.deb
$ sudo update-alternatives --config java

-> puc triar entre dues alternatives per al codi de Java

i ara ja puc modificar el fitxer makefile:

INC2=/usr/lib/j2sdk1.6-sun/include
INC3=/usr/lib/j2sdk1.6-sun/include/linux
$ sudo make

es crea el fitxer libJMidi.so.1.0

si no existís el directori /usr/lib/jni s'hauria de crear (no sé perquè em diu que jni és un fitxer. L'esborro i creo el directori)

$ sudo cp libJMidi.so.1.0  /usr/lib/jni
$ cd /usr/lib/jni
$ sudo ln -s libJMidi.so.1.0 libJMidi.so

Tutorial TutorialPart1.java

Nota: després de moltes proves, he aconseguit que soni

Ara ja estem en condicions de compilar un projecte Java: TutorialPart1.java

recopilem el tema de la compilació i execució de l'aplicació en mode consola (sense Eclipse). (per un tema de permisos he de posar sudo, en l'altra instal.lació no calia)

$ sudo javac AppletFrame.java
$ sudo javac -classpath /usr/src/midishare/lang/java/native:/usr/src/midishare/lang/java/samples/tutorial AppletFrame.java TutorialPart1.java
$ java -Djava.library.path=/usr/lib/jni -classpath /usr/src/midishare/lang/java/native:/usr/src/midishare/lang/java/samples/tutorial:/usr/src/midishare/lang/java/jni/linux/  TutorialPart1

compila bé i s'executa bé, però no se sent res. Ara entra en joc el driver msAlsaSeq.

$ msAlsaSeq -i 130:0 -o 128:0
WARNING: Unknown input address `130:0'

compte! no funciona (ahir funcionava):


Solució: faig

$ msAlsaSeq (engego el driver)
MidiShare ALSA driver anchored on "MidiShare/ALSA Bridge" is running.
Type 'q' to quit.

sense cap opció, i engego aquest client)

$ aconnect -i -o
...
cliente 129: 'MidiShare/ALSA Bridge' [tipo=usuario]
    0 'MidiShare/ALSA Bridge'

i veig que el MidiShare/ALSA Bridge té la referència 129 i no 130

$ msAlsaSeq -i 129:0 -o 128:0

-> ara ja es connecta bé, però si faig proves amb msconnect i mscontrol no sona res. També faig proves amb msdisplay per comprovar que estic enviant notes (OK). Ara no śe què passa que la ref torna ser 130, i ara ja puc jugar amb el mscontrol, però compte que pel canal 0 no sona res!! Només funcionen els canals 1->15 (i el 16 no hauria d'aparèixer). Deu ser un error de programació, però ahir crec que el canal 0 funcionava perfectament.

En el Test6 (TutorialPart1.java quan s'executa consta de varis tests) em surt la referència (ref 1) a la meva aplicació client que acabo d'obrir, i que em fa de pont entre MidiShare i la meva targeta real

<TEST 6> List every MidiShare client applications
List of MidiShare client applications
-------------------------------------
1 : reference number 0 name : MidiShare
2 : reference number 1 name : MidiShare/ALSA Bridge
3 : reference number 2 name : Tutorial -> es canvia a JavaTutorial

<TEST 10> Connect JavaTutorial to MidiShare -> de fet, hauria de connectar JavaTutorial a MidiShare/ALSA Bridge
<TEST 14> -> no se sent res

La connexió de JavaTutorial a MidiShare/ALSA Bridge la puc fer de dues maneres:

1) amb la utilitat msconnect, connectar MidiShare (ref0) amb MidiShare/ALSA Bridge (ref1) i també amb msdisplay (és útil veure aquesta informació. Una connexió es pot connectar a diferents destins: tecla Ctrl. És útil el msdisplay perquè puc veure el port i el canal).

Ara bé, quan engego msconnect les referències canvien... Lo important és que en el msconnect connecto el MidiShare, que sempre és ref0, amb el MidiShare/ALSA Bridge (que continua sent ref1)

No sento res perquè amb el msdisplay veig que les notes s'envien correctament, però pel port 0 i canal 0 que ja he vist que no funciona.

És com si el canal 0 estigués ocupat.

en el codi reemplaço Midi.SetChan(event,0); per Midi.SetChan(event,1); a tot arreu. (No oblidar-se de recompilar)

$ sudo chmod 777 *.java

(tenia problema amb els permisos d'escriptura)

Efectivament, envio pel canal 1 (ho veig amb el msdisplay, però encara no sento res) Però és lògic que el msdisplay vegi aquesta informació perquè la connexió amb el msdisplay la faig per codi:

if ((ref = Midi.GetNamedAppl("msdisplay")) > 0)	Midi.Connect(ourRefNum,ref, 1);

Per fi ho he aconseguit!: No m'he de fixar en Application -> Destination, sinó en Source -> Application La meva font és JavaTutorial (no pas MidiShare), i els meus destins són tarja_so i display

	void test14()
	{	int ref;
		text.appendText("\n\n<TEST 14>Send a note with pitch, velocity and duration\n");
		//if ((ref = Midi.GetNamedAppl("msdisplay")) > 0)	Midi.Connect(ourRefNum,ref, 1);
		//int ref_tarja_so;
		//if ((ref_tarja_so = Midi.GetNamedAppl("hola")) > 0)	Midi.Connect(ourRefNum,ref_tarja_so, 1);
		if ((ref = Midi.GetNamedAppl("msdisplay")) > 0)	System.out.println(ref);
		int ref_tarja_so;
		if ((ref_tarja_so = Midi.GetNamedAppl("tarja_so")) > 0)	System.out.println(ref_tarja_so);


		sendNote (72); 
	}

-> en el codi no cal fer Midi.Connect perquè això ja ho faig amb l'aplicació msconnect.

2) modificant el codi, connectant JavaTutorial (ref 2) a MidiShare/ALSA Bridge (ref 1) directament. fàcil

$ msAlsaSeq tarja_so -i 129:0/0 -o 128:0/0

-> tarja_so és el nom que li dono a la meva aplicació client (en comptes de MidiShare/ALSA Bridge)

	void test14()
	{	int ref;
		text.appendText("\n\n<TEST 14>Send a note with pitch, velocity and duration\n");
		//recordem que la següent línia no vol dir que msdiaplay hagi d'estar engegat, sinó que si està engegat em mostrarà el resultat
		if ((ref = Midi.GetNamedAppl("msdisplay")) > 0)	Midi.Connect(ourRefNum,ref, 1);
		int ref_tarja_so; //millor declarar aquesta variable allà on està declarada ref
		if ((ref_tarja_so = Midi.GetNamedAppl("tarja_so")) > 0)	Midi.Connect(ourRefNum,ref_tarja_so, 1);

		sendNote (72); 
	}

Era lògic que no sonés res sense modificar el codi. Els programadors de l'exemple fan servir msdisplay com a mètode de desenvolupament, sense fer sonar el so. És a dir, es pot programar sense hardware.

Ja tenim el TutorialPart1.java funcionant, en mode consola i en el Eclipse.

Tutorial TutorialPart2.java

D'entrada compila malament. Necessita MidiAppl

Part2 explains more advanced features of the MidiShare Java classes. You will learn here how to use the MidiAppl class which allows to manage incoming events and applications context switches. You will also learn how to use Midi tasks.

$ sudo javac -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial AppletFrame.java TutorialPart2.java

compila bé, però no és vàlid (falta MidiAppl, veure més avall)

$ sudo java -Djava.library.path=/usr/lib/jni -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial:/usr/src/midishare/lang/java/jni/linux/  TutorialPart2
Exception in thread "AWT-EventQueue-0" java.lang.Error: Unresolved compilation problems: 
        The method Open(String) is undefined for the type MidiTutorial
        MidiException cannot be resolved to a type
        e cannot be resolved

        at TutorialPart2.test1(TutorialPart2.java:157) -> appl.Open("TutorialPart2"); no sap obrir appl
        at TutorialPart2.action(TutorialPart2.java:283)
        at java.awt.Component.handleEvent(Component.java:6287)
        at java.awt.Component.postEvent(Component.java:4700)
        at java.awt.Component.postEvent(Component.java:4710)
        at java.awt.Component.postEvent(Component.java:4710)
        at java.awt.Component.dispatchEventImpl(Component.java:4429)
        at java.awt.Component.dispatchEvent(Component.java:4243)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

MidiTutorial appl; -> appl és un objecte de la classe MidiTutorial

appl = new MidiTutorial(this);

class MidiTutorial extends MidiAppl {...}

i la classe MidiTutorial ve de MidiAppl

al cap i a la fi, no sap el que és MidiAppl

dins la carpeta :/usr/src/midishare/lang/java/jni/linux tenim:

libJMidi.so.1.0 makefile makefile~ MidiAppl.o Midi.o

la classe MidiAppl.class (i MidiAppl.java) està a:

/usr/src/midishare/lang/java/native/grame/midishare/MidiAppl.class

$ sudo javac -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial /usr/src/midishare/lang/java/native/grame/midishare/MidiAppl.java TutorialPart2.java

compila bé -> s'ha de mirar com es tradueix això en el Eclipse

$ sudo java -Djava.library.path=/usr/lib/jni -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial:/usr/src/midishare/lang/java/jni/linux/  TutorialPart2

OK!

A Test4() agegeixo les línies

   int ref_tarja_so;
   if ((ref_tarja_so = Midi.GetNamedAppl("tarja_so")) > 0) Midi.Connect (appl.refnum,ref_tarja_so, 1);

i funciona! (pel canal 0, no cal fer el canal1. L'altre dia, no sé perquè, no sonava el canal 0)

Test5()

en comptes de fer servir el mskeyboard faig servir el mscontrol (mskeyboard no hi és a Linux, deu estar a Windows)

		int ref1, ref2, ref3;
		ref3 = Midi.GetNamedAppl("mscontrol");
		if (ref3 > 0)  Midi.Connect (ref3,appl.refnum, 1);

puc veure la referència dels mètodes (documentació) a: file:///usr/src/midishare/doc/html/index.html

La clau està en el mètode ReceiveAlarm (class MidiTutorial extends MidiAppl ):

	public void ReceiveAlarm(int event) 
	{
		switch (Midi.GetType(event)) {
		
			case Midi.typeNote:    // for Key event
			case Midi.typeKeyOn:
			case Midi.typeKeyOff:
				Midi.SetField(event, 0, Midi.GetField(event,0) + 12);// change the pitch field
				Midi.SetDate(event, Midi.GetDate(event)+1000);     // change the date field
				Midi.Send(refnum, event);							 // re-send the event
				break;
				
			default:
				Midi.FreeEv(event);		// otherwise dispose the event
				break;
		}
	}

que el que fa és capturar qualsevol dels 3 events (typeNote, typeKeyOn, typeKeyOff) i reenviar l'event Puc afegir la línia

			case Midi.typeProgChange:

per tal de què faci cas als events de programe Change. És a dir, ReceiveAlarm, en aquest cas, tal com està programat, fa de filtre.

A MidiAppl.java, que és la classe mare, trobem:

		public void ReceiveAlarm(int event){ Midi.FreeEv(event);}	
		/**
		The <b>ReceiveAlarm (ho he canviat)</b> method is automatically 
		called when a MidiShare context switch occurs.
 		The default method does nothing. This method can be redefined in derived classes.

Per tant, és obligatori posar aquest mètode. Si jo el que vull és reenviar tot el que es rep he de posar:

	public void ReceiveAlarm(int event) 
	{
				Midi.Send(refnum, event); // re-send the event
	}

carpeta tools: /usr/src/midishare/src/tools -> d'aquí puc treure codi en C que puc adaptar a Java

millor encara: /usr/src/midishare/src/linux/applications/samples

de fet, per a Java no es proporciona codi d'exemple

SimpleMidiShareTest.java

$ cd /home/joan/font_tutorial
$ sudo javac -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial testmidishare/SimpleMidiShareTest.java

compila bé -> s'ha de mirar com es tradueix això en el Eclipse

$ sudo java -Djava.library.path=/usr/lib/jni -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial  testmidishare.SimpleMidiShareTest

funciona. per tal de què soni, he de fer

$ msAlsaSeq tarja_so -i 129:0/0 -o 128:0/0

i afegir les línies

		int ref_tarja_so;
		if ((ref_tarja_so = Midi.GetNamedAppl("tarja_so")) > 0)	Midi.Connect(ourRefNum,ref_tarja_so, 1);

MidiShareTestIOtest.java

fa servir MidiAppl

$ sudo javac -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial /usr/src/midishare/lang/java/native/grame/midishare/MidiAppl.java testmidishare/MidiShareIOTest.java

compila bé -> s'ha de mirar com es tradueix això en el Eclipse

$ sudo java -Djava.library.path=/usr/lib/jni -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial:/usr/src/midishare/lang/java/jni/linux/ testmidishare.MidiShareIOTe
st

ja em sona. Afegeixo les línies:

			int ref_tarja_so, ref_display, ref_control;
			if ((ref_tarja_so = Midi.GetNamedAppl("tarja_so")) > 0)	Midi.Connect(midiHandler.refnum,ref_tarja_so, 1);
			if ((ref_display = Midi.GetNamedAppl("msdisplay")) > 0)	Midi.Connect(midiHandler.refnum,ref_display, 1);
			if ((ref_control = Midi.GetNamedAppl("mscontrol")) > 0)	Midi.Connect(ref_control,midiHandler.refnum, 1);

Fixem-nos que midiHandler.refnum es connecta a ref_tarja_so i ref_display, però ref_control es connecta a midiHandler.refnum (va al revés, mscontrol fa entrar notes).

Fallava el so perquè s'ha d'anar amb molt de compte amb els ports. En el codi original:

		// set these how you want them
		int inport = 0;
		int outport = 1;

però jo estic enviant a la tarja de so pel port 0: msAlsaSeq tarja_so -i 129:0/0 -o 128:0/0 per tant he de posar:

		int outport = 1;

A més a més, la tècnica utilitzada és deshabilitar tots els ports i només habilitar el que vull:

	/* kill active sensing */
	void configureFilter() {
		int i;
		for (i = 0; i < 256; i++) {
			//Midi.AcceptPort(filter, i, 1); -> accepto tots els ports
			Midi.AcceptPort(filter, i, 0); -> deshabilito tots els ports
			Midi.AcceptType(filter, i, 1);
		}

		for (i = 0; i < 16; i++) {
			Midi.AcceptChan(filter, i, 1);
		}
		Midi.AcceptPort(filter, inport, 1);
		Midi.AcceptType(filter, Midi.typeActiveSens, 0);
		//	Midi.AcceptType(filter, Midi.typeSysEx, 0);
		//	System.out.println("MidiShare configureFilter() filter#" + filter);
	}

Ara vull fer la segona part, que és escriure per pantalla els events que arriben. Faig servir mscontrol

MSReceiveTest.java

$ sudo javac -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial /usr/src/midishare/lang/java/native/grame/midishare/MidiAppl.java receive/MSReceiveTest.java

compila bé -> s'ha de mirar com es tradueix això en el Eclipse

$ sudo java -Djava.library.path=/usr/lib/jni -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial:/usr/src/midishare/lang/java/jni/linux/ receive.MSReceiveTest

compila i s'executa bé, però no puc fer-lo funcionar -> al final ja funciona, i és que el codi original que està bé és el de MidiShareTestIOtest. Per fer-lo funcionar he afegit

	/* kill active sensing */
	void configureFilter() {
		int i;
		for (i = 0; i < 256; i++) {
			//Midi.AcceptPort(filter, i, 1);
			Midi.AcceptPort(filter, i, 0);
			Midi.AcceptType(filter, i, 1);
		}

		for (i = 0; i < 16; i++) {
			Midi.AcceptChan(filter, i, 1);
		}
		Midi.AcceptPort(filter, 0, 1); //activem el port 0
		Midi.AcceptType(filter, Midi.typeActiveSens, 0);
		//	Midi.AcceptType(filter, Midi.typeSysEx, 0);
		//	System.out.println("MidiShare configureFilter() filter#" + filter);
	}
i
		int ref_tarja_so, ref_display, ref_control;
		if ((ref_tarja_so = Midi.GetNamedAppl("tarja_so")) > 0)	Midi.Connect(this.refnum,ref_tarja_so, 1);
		if ((ref_display = Midi.GetNamedAppl("msdisplay")) > 0)	Midi.Connect(this.refnum,ref_display, 1);
		if ((ref_control = Midi.GetNamedAppl("mscontrol")) > 0)	Midi.Connect(ref_control,this.refnum, 1);

Tanmateix, el configureFilter no calia en Windows. És a dir, he d'habilitar explícitament el port pel qual vull treballar. filter no cal declarar-ho, ve de la superclasse MidiAppl

Receive1

$ cd /home/joan/font_tutorial
$ sudo javac -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial /usr/src/midishare/lang/java/native/grame/midishare/MidiAppl.java receive/Receive1.java

compila bé -> s'ha de mirar com es tradueix això en el Eclipse

$ sudo java -Djava.library.path=/usr/lib/jni -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial:/usr/src/midishare/lang/java/jni/linux/ receive.Receive1

Va, però em trobo que a l'hora d'enviar la nota (sendnote) hi ha vegades que no se sent res. És com si la tarja de so estigués ocupada. Potser hi ha problemes amb la tarja de so interna... o bé hauré de trobar una manera fiable d'iniciar tot el sistema MIDI per tal que aquestes coses no passin.

no aconsegueixo veure les notes que entren

Receive2

$ sudo javac -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial /usr/src/midishare/lang/java/native/grame/midishare/MidiAppl.java receive/Receive2.java

compila bé -> s'ha de mirar com es tradueix això en el Eclipse

$ sudo java -Djava.library.path=/usr/lib/jni -classpath /usr/src/midishare/lang/java/native:/home/joan/font_tutorial:/usr/src/midishare/lang/java/jni/linux/ receive.Receive2

no em funciona, em funcionava en Windows


creat per Joan Quintana Compte, octubre 2008

Eines de l'usuari
Espais de noms
Variants
Accions
Navegació
Institut Jaume Balmes
Màquines recreatives
CNC
Informàtica musical
joanillo.org Planet
Eines