Compte rendu TP 5

Transcription

Compte rendu TP 5
Compte rendu TP 5
Auteur : Fenoll Loïse, Duminy Cédric, Oliva David
16 mars 2012
1
1.1
Périphérique de gestion du son
ALSA
Ci-dessous le code alsa.py que nous nous sommes appropré, auquel nous avons ajouter quelques
effet :
– Un détecteur de son, qui fait un signal sonore lorsqu’il détecte un son justement
– Enregistrer un morceau, et le jouer avec un écho. Pour cela nous avons repéter le son récupérer
avec un delaie, en insérant des blancs entre les échos
– Enregistrer un son et le mettre en effet de résonance. Nous faisons donc simplement un effet
d’échos, avec 6 echos, de 0.1 seconde, pour donner un effet de superposition du son.
– Enregistrer un son et l’allonger. Il y a 2 methode pour cela, une consistant a baisser la
fréquence d’echantillonnage de moitié, et une autre multipliant chaque fréquence par un
certain coefficient voulu (de base 2, le doublant ainsi)
– Amplifier un son. Nous avons pour cela multipilé pour gagner en hauteur le signal. Nous
avons effectué ce test avec un Do, en important notre ancienne classe Son.
# !/ usr / bin / env python
# _ * _ coding : utf -8 * _ *
’’’
Created on 2 feb . 2010
@author : G . Menez
from http :// snippets . dzone . com / posts / show /9661
from http :// ubuntuforums . org / showthread . php ? t =500337
" Alsa " experiment
’’’
import alsaaudio
import struct
import time
import audioop
from math import sin , pi
def read_f rom_ca rd ( channels =2 , fe =8000 , fmt = alsaaudio . PCM_FORMAT_S16_LE , periodsize
=160 , mode = alsaaudio . PCM_NORMAL ) :
"""
Default card attributes : Mono , 8000 Hz , 16 bit little endian samples
Pour comprendre la difference entre les modes = > fonction read dans
http :// pyalsaaudio . sourceforge . net / libalsaaudio . html
"""
inp = alsaaudio . PCM ( type = alsaaudio . PCM_CAPTURE , mode = mode )
inp . setchannels ( channels )
inp . setrate ( fe )
inp . setformat ( fmt )
# The period size controls the internal number of frames per period .
# The significance of this parameter is documented in the ALSA api .
1
# For our purposes , it is sufficient to know that reads from the device
# will return THIS many frames .
# Each frame being 2 bytes long .
# This means that the reads below will return either 320 bytes of data
# or 0 bytes of data .
# The latter is possible if we are in nonblocking mode .
inp . setperiodsize ( periodsize )
while True :
# Read data from device
l , data = inp . read ()
if l :
# Return the maximum of the absolute value of all samples in a fragment
.
if ( fmt == alsaaudio . P C M _ F O R M A T _ S 1 6 _ L E ) :
width = 2 # 2 octets
print " fragment of " , l , " samples : " , audioop . max ( data , width )
if ( mode == alsaaudio . PCM_NONBLOCK ) :
time . sleep (.001)
def r e a d _ d u r a t i o n _ f r o m _ c a r d ( duration , channels =2 , fe =8000 , format = alsaaudio .
PCM_FORMAT_S16_LE , periodsize =160 , mode = alsaaudio . PCM_NORMAL ) :
"""
Default card attributes : Mono , 8000 Hz , 16 bit little endian samples
Pour comprendre la difference entre les modes = > fonction read dans
http :// pyalsaaudio . sourceforge . net / libalsaaudio . html
"""
inp = alsaaudio . PCM ( type = alsaaudio . PCM_CAPTURE , mode = mode )
inp . setchannels ( channels )
inp . setrate ( fe )
inp . setformat ( format )
# The period size controls the internal number of frames per period .
# The significance of this parameter is documented in the ALSA api .
# For our purposes , it is sufficient to know that reads from the device
# will return THIS many frames .
# Each frame being 2 bytes long .
# This means that the reads below will return either 320 bytes of data
# or 0 bytes of data .
# The latter is possible if we are in nonblocking mode .
inp . setperiodsize ( periodsize )
lt = 0
ld = ( duration * fe )
# print " ld : " , ld
alldata = []
while lt < ld :
# Read data from device
l , data = inp . read ()
if l :
# Return the maximum of the absolute value of all samples in a fragment
.
if ( format == alsaaudio . P C M _ F O R M A T _ S 1 6 _ L E ) :
width = 2 # 2 octets
# print " The max value of fragment of " , l , " samples is :" , audioop . max
( data , width )
alldata . extend ( struct . unpack ( " <" + str ( channels * l ) + ’h ’ , data ) )
lt += l
if ( mode == alsaaudio . PCM_NONBLOCK ) :
time . sleep (.001)
2
return alldata , lt
def g en er a te _ st er e o ( fe =44100 , periodsize =44100) :
"""
A list with the binaural beats ( sinusoidal ) signals is built
periodsize = fe : Une seconde de signal
Il y a des contraintes sur ce parametre
cf http :// pyalsaaudio . sourceforge . net / libalsaaudio . html
"""
maxAmp = pow (2 ,31) - 1 # Les samples de la liste sont sur 32 bits !
# Channel 1
frec1 =317.0 # Frequency
vol1 =1
# Coef Volume max = > 1
# Channel 2
frec2 =323.0 # Frequency
vol2 =1
# Coef Volume max = > 1
list = []
i = periodsize
while (i >0) :
list . append ( maxAmp * vol1 * sin ( i *( frec1 / fe ) *2.0* pi ) )
list . append ( maxAmp * vol2 * sin ( i *( frec2 / fe ) *2.0* pi ) )
i -=1
return list
def write_to_card ( samples , channels =1 , fe =8000 , format = alsaaudio . PCM_FORMAT_S32_LE ,
periodsize =160) :
# device initia lizati on
out = alsaaudio . PCM ( type = alsaaudio . PCM_PLAYBACK , mode = alsaaudio . PCM_NORMAL ,
card = ’ default ’)
out . setchannels ( channels )
out . setrate ( fe )
out . setformat ( format )
c
out . setperiodsize ( periodsize ) # nombre de frames traità es
par chaque write
if ( format == alsaaudio . P C M _ F O R M A T _ S 3 2 _ L E ) :
fmt = ’l ’
if ( format == alsaaudio . P C M _ F O R M A T _ S 1 6 _ L E ) :
fmt = ’h ’
s = struct . pack ( ’ < ’+ channels * periodsize * fmt ,* samples )
# while (1) : # The list is written over and over again . Just kill the process to
stop .
out . write ( s )
def detecteur_son ( channels =2 , fe =8000 , fmt = alsaaudio . PCM_FORMAT_S16_LE , periodsize
=80 , mode = alsaaudio . PCM_NORMAL ) :
"""
Default card attributes : Mono , 8000 Hz , 16 bit little endian samples
Pour comprendre la difference entre les modes = > fonction read dans
http :// pyalsaaudio . sourceforge . net / libalsaaudio . html
"""
inp = alsaaudio . PCM ( type = alsaaudio . PCM_CAPTURE , mode = mode )
inp . setchannels ( channels )
inp . setrate ( fe )
inp . setformat ( fmt )
out = alsaaudio . PCM ( type = alsaaudio . PCM_PLAYBACK , mode = alsaaudio . PCM_NORMAL ,
card = ’ default ’)
out . setchannels ( channels )
out . setrate ( fe )
out . setformat ( fmt )
3
c
out . setperiodsize ( periodsize ) # nombre de frames traità es
par chaque write
if ( fmt ==
format
if ( fmt ==
format
alsaaudio . P C M _ F O R M A T _ S 3 2 _ L E ) :
= ’h ’
alsaaudio . P C M _ F O R M A T _ S 1 6 _ L E ) :
= ’l ’
maxAmp = pow (2 ,31) - 1 # Les samples de la liste sont sur 32 bits !
# Channel 1
frec1 =317.0 # Frequency
vol1 =1
# Coef Volume max = > 1
# Channel 2
frec2 =323.0 # Frequency
vol2 =1
# Coef Volume max = > 1
list = []
i = periodsize
while (i >0) :
list . append ( maxAmp * vol1 * sin ( i *( frec1 / fe ) *2.0* pi ) )
list . append ( maxAmp * vol2 * sin ( i *( frec2 / fe ) *2.0* pi ) )
i -=1
# The period size controls the internal number of frames per period .
# The significance of this parameter is documented in the ALSA api .
# For our purposes , it is sufficient to know that reads from the device
# will return THIS many frames .
# Each frame being 2 bytes long .
# This means that the reads below will return either 320 bytes of data
# or 0 bytes of data .
# The latter is possible if we are in nonblocking mode .
inp . setperiodsize ( periodsize )
while True :
# Read data from device
l , data = inp . read ()
if l :
# Return the maximum of the absolute value of all samples in a fragment
.
if ( fmt == alsaaudio . P C M _ F O R M A T _ S 1 6 _ L E ) :
width = 2 # 2 octets
print " fragment of " , l , " samples : " , audioop . max ( data , width )
if audioop . max ( data , width ) > 150:
s = struct . pack ( ’ < ’+ channels * periodsize * format ,* list )
out . write ( s )
if ( mode == alsaaudio . PCM_NONBLOCK ) :
time . sleep (.101)
# time . sleep (.501)
"""
Methode servant a enregistrer le son par le micro
Le fonctionement de cette fonction se base sur le modèle de la fonction ci - dessus
"""
def e n r e g i s t r e u r _ s o n ( channels =2 , fe =8000 , format = alsaaudio . PCM_FORMAT_S16_LE ,
periodsize =80 , mode = alsaaudio . PCM_NORMAL ) :
"""
Default card attributes : Mono , 8000 Hz , 16 bit little endian samples
Pour comprendre la difference entre les modes = > fonction read dans
http :// pyalsaaudio . sourceforge . net / libalsaaudio . html
"""
inp = alsaaudio . PCM ( type = alsaaudio . PCM_CAPTURE , mode = mode )
inp . setchannels ( channels )
inp . setrate ( fe )
inp . setformat ( format )
4
# The period size controls the internal number of frames per period .
# The significance of this parameter is documented in the ALSA api .
# For our purposes , it is sufficient to know that reads from the device
# will return THIS many frames .
# Each frame being 2 bytes long .
# This means that the reads below will return either 320 bytes of data
# or 0 bytes of data .
# The latter is possible if we are in nonblocking mode .
inp . setperiodsize ( periodsize )
lt = 0
dejaLu = False
# print " ld : " , ld
alldata = []
while True :
# Read data from device
l , data = inp . read ()
if l :
# Return the maximum of the absolute value of all samples in a fragment
.
if ( format == alsaaudio . P C M _ F O R M A T _ S 1 6 _ L E ) :
width = 2 # 2 octets
print " The max value of fragment of " , l , " samples is : " , audioop . max (
data , width )
if audioop . max ( data , width ) > 100:
alldata . extend ( struct . unpack ( " <" + str ( channels * l ) + ’h ’ , data ) )
lt += l
dejaLu = True
elif dejaLu == True and lt > fe :
return alldata , lt
if ( mode == alsaaudio . PCM_NONBLOCK ) :
time . sleep (.001)
return alldata , lt
"""
Methode servant a creer des echos a partir d ’ echantillons
Le fonctionement est celui decrit dans le sujet
"""
def creer_echo ( samples , fe =8000 , channels =2 , seconde =1 , nombreEcho =4) :
nombreEcho += 1
echo = []
DELAY = int ( seconde * fe )
compteurEcho = 0
while compteurEcho < nombreEcho :
decalage = compteurEcho * DELAY
volume = ( nombreEcho - compteurEcho ) / float ( nombreEcho ) *5
print " decalage : " , decalage
print " volume : " , volume
for i in range ( decalage , len ( samples ) + decalage , 1) :
if i < len ( samples ) and decalage != 0:
echo [ i ] += volume * samples [i - decalage ]
else :
echo . append ( volume * samples [i - decalage ])
echo = insererBlanc ( echo , decalage )
compteurEcho += 1
while len ( echo ) % channels != 0:
echo . append (0)
print " channels : " , channels
print " samples : " , len ( samples )
5
print " DELAY : " , DELAY
print " echo : " , len ( echo ) / channels
return echo , len ( echo ) / channels
"""
Fonction permettant l ’ insertion de blanc après la serie d ’ echantillons
"""
def insererBlanc ( samples , delay ) :
while len ( samples ) < delay :
samples . append (0)
return samples
"""
Fonction de resonnance se basant sur la creation d ’ echo avec des parametres bien
particuliers
"""
def resonance ( samples , fe =8000 , channels =2) :
return creer_echo ( samples , fe =8000 , channels =2 , seconde =0.1 , nombreEcho =6)
"""
Fonction servant à creer un allongement
On multiplie par coeff le temps de chaque echantillon
"""
def allongement ( samples , coeff = 2) :
allong = []
for i in range ( len ( samples ) ) :
for j in range ( coeff ) :
allong . append ( samples [ i ])
return allong
# ------------------------------------------------------if __name__ == ’ __main__ ’:
channels = 2
fe = 44100
"""
print " Playing "
list = ge ne r at e_ s te r eo ( fe , fe )
write_to_card ( samples = list , channels = channels , fe = fe , format = alsaaudio .
PCM_FORMAT_S32_LE , periodsize = fe )
print " Recording "
snd , lt = r e a d _ d u r a t i o n _ f r o m _ c a r d (4)
write_to_card ( samples = snd , channels =2 , fe =8000 , format = alsaaudio .
PCM_FORMAT_S16_LE , periodsize = lt )
"""
print " E nregis tremen t ... "
snd , lt = e n r e g i s t r e u r _ s o n ( channels = channels )
print " Lecture ... "
"""
c
Effet de rà sonance
"""
res , lt1 = resonance ( snd , fe =8000 , channels = channels )
write_to_card ( samples = res , channels = channels , fe =8000 , format = alsaaudio .
PCM_FORMAT_S16_LE , periodsize = lt1 )
"""
c
Effet d ’Ãcho
"""
# ech , lt2 = creer_echo ( snd , fe =8000 , channels = channels , seconde =1.5 , nombreEcho =6)
# write_to_card ( samples = ech , channels = channels , fe =8000 , format = alsaaudio .
PCM_FORMAT_S16_LE , periodsize = lt2 )
"""
Effet d ’ allongement
"""
# allong = allongement ( snd )
# write_to_card ( samples = allong , channels = channels , fe =16000 , format = alsaaudio .
PCM_FORMAT_S16_LE , periodsize =2* lt )
6
1.2
Wiimote
Voici le mode d’emploi de notre programme :
– Avec 1 à 2 wiimotes :
> En les connectant successivement en appuyant simultanement sur les boutons 1 et 2, on
peut jouer de la batterie.
> Si deux wiimotes sont connectées, les sons de toms sont attribue à la première wiimote, et
les sons de cymbale à a la deuxième.
> Pour changer de son, il faut jouer en restant appuyer sur les boutons correspondants aux
autres sons (que ce soit de toms ou de cymbale, qui sont au choix gauche, droite, haut ou
bas
> En appuyant sur le bouton "home", on passe en mode bruit divers. Ainsi en appuyant sur
A, on ouvre un sabre laser, que l’on referme en appuyant sur A à nouveau.
> En appuyant sur le bouton B on peut faire des tirs lazer.
> Lorsque que l’on est en mode bruit divers, si le mode "star wars" n’est pas declenché, en
retournant la manette, on obtient une boite à "meuh".
– Avec 1 wiimote et une nunchuk :
> La wiimote et le nunchuk font office de baguette sur les tambours, toms et caisse claire.
Lorsque l’ont met le joystick du nunchuk vers le haut, on obtient les cymbales.
> Pour changer de son, il faut rester appuyer tout en jouant sur les boutons suivant au choix :
A, B, C ou Z.
> Le mode de son Star Wars et boite à meuh est aussi disponible avec la wiimote.
Ayant pensé trop tard à utiliser les threads, nous avons utiliser les créations de processus fils,
afin que les sons ne se chevauchent pas, et ne pas saturer la carte son.
Pour ne avoir à rouvrir les fichiers sons à chaque utilisation, nous les avons prechargé au
préalable, que nous utilisons dès la creation d’un objet worker. Ainsi lorsque nous avons besoin de
jouer un son, on appelle une instance de la classe worker. La lecture des sons est simplement faire
par alsaaudio, et ecrite sur la carte son.
Nous avons creé un petit menu permettant de choisir sa configuration, afin que le programme
soit utilisable pleinement si on possède une ou deux wiimote, ou une wiimote avec un nunchuk.
En ce qui concerne les calculs de variation de la wiimote lors de la batterie, nous avions utiliser
une comparaison de variation, avec une condition lourde, puis nous avons opter finalement pour
une comparaison de valeur, plus efficace et plus lisible. Nous calculons si le mouvement s’effectue
de haut en bas, alors seulement nous emettons un son, voir une vibration si aucun nunchuk est
detecte. L’action de mouvement de bas vers haut empêche ce son, pour imiter pleinement un jeu
de batterie. Il en est de méme pour les cymbales.
Lorsqu’on est en mode Star Wars, en appuyant sur A on peut donc ouvrir un sabre laser.
Cette action d’appuyer sur A l’ouvre et le referme, et selon lance un son différent. Mais surtout le
calcul de variation de la wiimote, et donc le son ambiant n’est possible que lorsque le sabre laser
est ouvert. Ainsi lorsque le sabre est ouvert, on diffuse en continue un son ambiant, et selon les
variations un son de combat. Pour ces combats, en donnant de petit coup ou un grand coup, on
obtient un son différent.
Quand à la boite à meuh, elle n’est active que si le sabre laser est ferme. De plus le son ne
s’active que lorsque la wiimote est à l’envers. Par contre, si la wiimote remonte, ce son se coupe.
7
# !/ usr / bin / python
’’’
Created on 19 janv . 2011
@author : menez
https :// github . com / abstrakraft / cwiid
apt - get install libcwiimote - dev python - cwiid
’’’
import matplotlib . pyplot as plt
import sys
import cwiid
import threading
import time
import numpy as np
import alsa
import alsaaudio
from alsa import *
import signal
import os
import wave
class worker ( threading . Thread ) :
"""
Ini tialis ation de la classe worker
"""
def __init__ ( self , cwiid ) :
threading . Thread . __init__ ( self )
worker . p r e c h a r g e m e n t W a v ()
self . cwiid = cwiid
self . reset ()
"""
Calcul des valeurs x , y , z ( absice , ordonne , profondeur ) de la wiimote , et du
nunchuk si celui - ci est connecte
CHoix du mode batterie ou Star Wars , qui enclenche un calcul de variation
different .
Deconnexion de la wiimote si les touches 1 et 2 sont enclenchees simultanement
"""
def run ( self ) :
while ( True ) :
wx = self . cwiid . state [ ’ acc ’ ][ cwiid . X ]
wy = self . cwiid . state [ ’ acc ’ ][ cwiid . Y ]
wz = self . cwiid . state [ ’ acc ’ ][ cwiid . Z ]
if self . cwiid . state . has_key ( ’ nunchuk ’) :
nx = self . cwiid . state [ ’ nunchuk ’ ][ ’ acc ’ ][ cwiid . X ]
ny = self . cwiid . state [ ’ nunchuk ’ ][ ’ acc ’ ][ cwiid . Y ]
nz = self . cwiid . state [ ’ nunchuk ’ ][ ’ acc ’ ][ cwiid . Z ]
if ( self . A == True ) :
self . wxt . append ( wx ) ;
self . wyt . append ( wy ) ;
self . wzt . append ( wz ) ;
if self . cwiid . state . has_key ( ’ nunchuk ’) :
self . nxt . append ( nx ) ;
self . nyt . append ( ny ) ;
self . nzt . append ( nz ) ;
if self . cwiid . state [ ’ buttons ’] & cwiid . BTN_HOME and self .
chan gement Etat :
worker . batterie = not ( worker . batterie )
self . c hangem entEta t = False
8
self . compteARebour (1)
if worker . batterie :
self . c a l c u l e r V a r i a t i o n B a t t e r i e ()
else :
self . autreSon ()
if self . cwiid . state [ ’ buttons ’] & cwiid . BTN_2 and self . cwiid . state [ ’
buttons ’] & cwiid . BTN_1 :
print " Arret du programme "
self . A = False
self . libererWav ()
sys . exit (0)
time . sleep (0.005)
"""
Ini tialis ation des valeurs
"""
def reset ( self ) :
self . wxt = []
self . wyt = []
self . wzt = []
self . nxt = []
self . nyt = []
self . nzt = []
self . A = True
self . w iimote Remont e = True
self . n unchuk Remont e = True
self . pid1 = os . getpid ()
self . pid2 = os . getpid ()
worker . batterie = True
self . sonStarWars = False
self . c hangem entEta t = True
self . j ouerBo iteMeu h = True
self . i = 0
def stop ( self ) :
self . A = False
np . savetxt ( " wii . txt " , np . array ( zip ( self . wxt , self . wyt , self . wzt ) ) , fmt = ’% i
% i % i ’)
"""
Cette fonction precharge tout les sons , pour ne pas les ouvrir a chaque
utilisation
On ajoute a chaque variable de son son fichier wav attribue , ainsi que son
nombre de trames
"""
@staticmethod
def p r e c h a r g e m e n t W a v () :
worker . batterie1 = []
worker . batterie2 = []
worker . batterie3 = []
worker . batterie4 = []
worker . batterie5 = []
worker . cymbale1
worker . cymbale2
worker . cymbale3
worker . cymbale4
worker . cymbale5
=
=
=
=
=
[]
[]
[]
[]
[]
worker . allumageSW = []
worker . eteignageSW = []
worker . ambiantSW = []
worker . ventCourtSW = []
9
worker . ventLongSW = []
worker . tirSW = []
worker . boiteMeuh = []
worker . batterie1 . append ( wave . open ( " ./ son / sonBatterie / Toms2 / tom1 . wav " , " r " ) )
worker . batterie1 . append ( worker . batterie1 [0]. readframes ( worker . batterie1 [0].
getnframes () ) )
worker . batterie2 . append ( wave . open ( " ./ son / sonBatterie / Toms2 / tom2 . wav " , " r " ) )
worker . batterie2 . append ( worker . batterie2 [0]. readframes ( worker . batterie2 [0].
getnframes () ) )
worker . batterie3 . append ( wave . open ( " ./ son / sonBatterie / Toms2 / tom3 . wav " , " r " ) )
worker . batterie3 . append ( worker . batterie3 [0]. readframes ( worker . batterie3 [0].
getnframes () ) )
worker . batterie4 . append ( wave . open ( " ./ son / sonBatterie / Toms2 / tom4 . wav " , " r " ) )
worker . batterie4 . append ( worker . batterie4 [0]. readframes ( worker . batterie4 [0].
getnframes () ) )
worker . batterie5 . append ( wave . open ( " ./ son / sonBatterie / Toms2 / tom5 . wav " , " r " ) )
worker . batterie5 . append ( worker . batterie5 [0]. readframes ( worker . batterie5 [0].
getnframes () ) )
worker . cymbale1 . append ( wave . open ( " ./ son / sonBatterie / Cymbale2 / Cymbale1 . wav " ,
"r"))
worker . cymbale1 . append ( worker . cymbale1 [0]. readframes ( worker . cymbale1 [0].
getnframes () ) )
worker . cymbale2 . append ( wave . open ( " ./ son / sonBatterie / Cymbale2 / Cymbale2 . wav " ,
"r"))
worker . cymbale2 . append ( worker . cymbale2 [0]. readframes ( worker . cymbale2 [0].
getnframes () ) )
worker . cymbale3 . append ( wave . open ( " ./ son / sonBatterie / Cymbale2 / Cymbale3 . wav " ,
"r"))
worker . cymbale3 . append ( worker . cymbale3 [0]. readframes ( worker . cymbale3 [0].
getnframes () ) )
worker . cymbale4 . append ( wave . open ( " ./ son / sonBatterie / Cymbale2 / Cymbale4 . wav " ,
"r"))
worker . cymbale4 . append ( worker . cymbale4 [0]. readframes ( worker . cymbale4 [0].
getnframes () ) )
worker . cymbale5 . append ( wave . open ( " ./ son / sonBatterie / Cymbale2 / Cymbale5 . wav " ,
"r"))
worker . cymbale5 . append ( worker . cymbale5 [0]. readframes ( worker . cymbale5 [0].
getnframes () ) )
worker . allumageSW . append ( wave . open ( " ./ son / autreSon / StarWars / Allumage . wav " ,
"r"))
worker . allumageSW . append ( worker . allumageSW [0]. readframes ( worker . allumageSW
[0]. getnframes () ) )
worker . eteignageSW . append ( wave . open ( " ./ son / autreSon / StarWars / Eteignage . wav "
, "r"))
worker . eteignageSW . append ( worker . eteignageSW [0]. readframes ( worker .
eteignageSW [0]. getnframes () ) )
worker . ambiantSW . append ( wave . open ( " ./ son / autreSon / StarWars / Ambiant . wav " , " r
"))
worker . ambiantSW . append ( worker . ambiantSW [0]. readframes ( worker . ambiantSW [0].
getnframes () ) )
worker . ventCourtSW . append ( wave . open ( " ./ son / autreSon / StarWars / VentCourt . wav "
, "r"))
worker . ventCourtSW . append ( worker . ventCourtSW [0]. readframes ( worker .
ventCourtSW [0]. getnframes () ) )
worker . ventLongSW . append ( wave . open ( " ./ son / autreSon / StarWars / VentLong . wav " ,
"r"))
worker . ventLongSW . append ( worker . ventLongSW [0]. readframes ( worker . ventLongSW
[0]. getnframes () ) )
worker . tirSW . append ( wave . open ( " ./ son / autreSon / StarWars / TirVaisseau . wav " , " r
"))
worker . tirSW . append ( worker . tirSW [0]. readframes ( worker . tirSW [0]. getnframes ()
))
10
worker . boiteMeuh . append ( wave . open ( " ./ son / autreSon / BoiteMeuh . wav " , " r " ) )
worker . boiteMeuh . append ( worker . boiteMeuh [0]. readframes ( worker . boiteMeuh [0].
getnframes () ) )
"""
Comme son nom l ’ indique , cette fonction ferme tous les fichiers de son
"""
def libererWav ( self ) :
worker . batterie1 [0]. close ()
worker . batterie2 [0]. close ()
worker . batterie3 [0]. close ()
worker . batterie4 [0]. close ()
worker . batterie5 [0]. close ()
worker . cymbale1 [0]. close ()
worker . cymbale2 [0]. close ()
worker . cymbale3 [0]. close ()
worker . cymbale4 [0]. close ()
worker . cymbale5 [0]. close ()
worker . allumageSW [0]. close ()
worker . eteignageSW [0]. close ()
worker . ambiantSW [0]. close ()
worker . ventCourtSW [0]. close ()
worker . ventLongSW [0]. close ()
worker . tirSW [0]. close ()
self . boiteMeuh [0]. close ()
"""
Cette fonction permet un delai entre le mode Star Wars et celui de batterie .
Elle permet de ne pas saturer ce changement de mode en appuyant sur le bouton
home
"""
def compteARebour ( self , length ) :
start = time . time ()
while not ( self . c hangem entEta t ) :
if time . time () - start >= length :
self . c hangem entEta t = True
"""
Ici on reutilise les fonctions de l ’ exercice precedent , avec alasaaudio
Avec un son passe en parametre , que l ’ on ecrit sur la carte son
"""
def lireSo nFichi er ( self , son ) :
if son [0]. tell () == 0:
son [0]. setpos (0)
out = alsaaudio . PCM ( type = alsaaudio . PCM_PLAYBACK , mode = alsaaudio . PCM_NORMAL ,
card = ’ default ’)
out . setchannels ( son [0]. getnchannels () )
out . setformat ( alsaaudio . P C M _ F O R M A T _ S 1 6 _ L E )
out . setrate ( son [0]. getframerate () )
out . write ( son [1])
out . close ()
"""
La fonction pour lancer la vibration de la wiimote ( lorsque l ’ on joue de la
batterie sans nunchuk )
"""
def faireVibrer ( self , temps ) :
self . cwiid . rumble = 1
time . sleep ( temps )
self . cwiid . rumble = 0
11
"""
Cette fonction determine selon sa configuration les sons a jouer .
Ainsi , si on possede un nunchuk , et que son joystick est pointe vers le haut ,
on lance la fonction des son de cymbale ,
sinon il jouera de la batterie
Quant aux wiimotes , la premiere wiimote ( qu ’ elle soit seul ou non , elle a la
led 1 allume , ce qui la rend r econna issabl e ) joue de la batterie .
Si une deuxieme wiimote est connecte , elle a donc la led 2 allume , et les sons
de cymbales lui sont attribue
"""
def j o u e r S o n B a t t e r i e ( self ) :
if self . cwiid . state . has_key ( ’ nunchuk ’) :
item = self . cwiid . state [ ’ nunchuk ’ ][ ’ stick ’]
if item [0] < 50 or item [0] > 190 or item [1] < 50 or item [1] > 190:
self . sonCymbale ()
else :
self . sonCaisse ()
else :
if self . cwiid . state [ ’ led ’] & eval ( ’ cwiid . LED1_ON ’) :
self . sonCaisse ()
elif self . cwiid . state [ ’ led ’] & eval ( ’ cwiid . LED2_ON ’) :
self . sonCymbale ()
"""
Cette fonction configure les sons de batterie a joue selon les boutons ( et les
manettes connectees ) , avec un son par defaut
"""
def sonCaisse ( self ) :
if self . cwiid . state . has_key ( ’ nunchuk ’) :
if self . cwiid . state [ ’ buttons ’] & cwiid . BTN_A :
self . l ireSon Fichie r ( worker . batterie1 )
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_B :
self . l ireSon Fichie r ( worker . batterie2 )
elif self . cwiid . state [ ’ nunchuk ’ ][ ’ buttons ’] & cwiid . NUNCHUK_BTN_C :
self . l ireSon Fichie r ( worker . batterie3 )
elif self . cwiid . state [ ’ nunchuk ’ ][ ’ buttons ’] & cwiid . NUNCHUK_BTN_Z :
self . l ireSon Fichie r ( worker . batterie5 )
else :
self . l ireSon Fichie r ( worker . batterie4 )
else :
if self . cwiid . state [ ’ buttons ’] & cwiid . BTN_LEFT :
self . l ireSon Fichie r ( worker . batterie1 )
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_RIGHT :
self . l ireSon Fichie r ( worker . batterie2 )
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_UP :
self . l ireSon Fichie r ( worker . batterie3 )
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_DOWN :
self . l ireSon Fichie r ( worker . batterie4 )
else :
self . l ireSon Fichie r ( worker . batterie5 )
"""
Comme la precedente , cette fonction configure les sons selons les boutons et
les manettes , mais de cymbale cette fois - ci
"""
def sonCymbale ( self ) :
if self . cwiid . state . has_key ( ’ nunchuk ’) :
if self . cwiid . state [ ’ buttons ’] & cwiid . BTN_A :
self . l ireSon Fichie r ( worker . cymbale1 )
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_B :
self . l ireSon Fichie r ( worker . cymbale2 )
elif self . cwiid . state [ ’ nunchuk ’ ][ ’ buttons ’] & cwiid . NUNCHUK_BTN_C :
self . l ireSon Fichie r ( worker . cymbale3 )
elif self . cwiid . state [ ’ nunchuk ’ ][ ’ buttons ’] & cwiid . NUNCHUK_BTN_Z :
self . l ireSon Fichie r ( worker . cymbale4 )
else :
12
self . l ireSon Fichie r ( worker . cymbale5 )
else :
if self . cwiid . state [ ’ buttons ’] & cwiid . BTN_LEFT :
self . l ireSon Fichie r ( worker . cymbale1 )
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_RIGHT :
self . l ireSon Fichie r ( worker . cymbale2 )
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_UP :
self . l ireSon Fichie r ( worker . cymbale3 )
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_DOWN :
self . l ireSon Fichie r ( worker . cymbale4 )
else :
self . l ireSon Fichie r ( worker . cymbale5 )
"""
Cette fonction calcule les variations de la batterie .
Les codes mit en commentaire fonctionne , la seul difference par rapport a
chaque code qui les suit ,
c ’ est que le code en commentaire est une comparaison de variation , et celui en
dessous est une comparaison de valeur .
Ce dernier etant plus efficace , c ’ est celui que nous avons garde
De plus , lorsqu ’ on a l ’ action de descente de la wiimote ,
et uniquement si il n ’y a pas de nunchuk accroche , la wiimote vibre , pour
imiter une resonnance avec la batterie .
"""
def c a l c u l e r V a r i a t i o n B a t t e r i e ( self ) :
deltaX = 5
deltaY = 10
deltaZ = 20
"""
Calcule si la wiimote descend
if self . w iimote Remont e == True and \
len ( self . wxt ) > 5 and \
np . abs ( self . wxt [ len ( self . wxt ) -1] - self . wxt [ len ( self . wxt ) -2]) < deltaX and \
np . abs ( self . wyt [ len ( self . wyt ) -1] - self . wyt [ len ( self . wyt ) -2]) < deltaY and \
self . wzt [ len ( self . wzt ) -2] - self . wzt [ len ( self . wzt ) -3] +\
self . wzt [ len ( self . wzt ) -3] - self . wzt [ len ( self . wzt ) -4] +\
self . wzt [ len ( self . wzt ) -4] - self . wzt [ len ( self . wzt ) -5] > deltaZ :
"""
if self . w iimote Remont e == True and \
len ( self . wxt ) > 2 and \
np . abs ( self . wxt [ len ( self . wxt ) -1] - self . wxt [ len ( self . wxt ) -2]) < deltaX and \
self . wzt [ len ( self . wzt ) -1] > 170:
print " Descente wiimote "
if self . pid1 != os . getpid () :
os . kill ( self . pid1 , signal . SIGKILL )
self . pid1 = os . fork ()
if self . pid1 == 0:
self . j o u e r S o n B a t t e r i e ()
sys . exit (0)
else :
if not self . cwiid . state . has_key ( ’ nunchuk ’) :
if self . pid2 != os . getpid () :
os . kill ( self . pid2 , signal . SIGKILL )
self . pid2 = os . fork ()
if self . pid2 == 0:
time . sleep (0.1)
self . faireVibrer (0.1)
sys . exit (0)
time . sleep (0.0750)
self . w iimote Remont e = False
"""
Calcule si le nunchuk descend
"""
13
if self . cwiid . state . has_key ( ’ nunchuk ’) :
if self . n unchuk Remont e == True and \
len ( self . nxt ) > 5 and \
np . abs ( self . nxt [ len ( self . nxt ) -1] - self . nxt [ len ( self . nxt ) -2]) < deltaX
and \
np . abs ( self . nyt [ len ( self . nyt ) -1] - self . nyt [ len ( self . nyt ) -2]) < deltaY
and \
np . abs ( self . nzt [ len ( self . nzt ) -1] - self . nzt [ len ( self . nzt ) -2]) < 5 and \
self . nzt [ len ( self . nzt ) -2] - self . nzt [ len ( self . nzt ) -3] +\
self . nzt [ len ( self . nzt ) -3] - self . nzt [ len ( self . nzt ) -4] +\
self . nzt [ len ( self . nzt ) -4] - self . nzt [ len ( self . nzt ) -5] > deltaZ :
print " Descente nunchuk "
if self . pid2 != os . getpid () :
os . kill ( self . pid2 , signal . SIGKILL )
self . pid2 = os . fork ()
if self . pid2 == 0:
self . j o u e r S o n B a t t e r i e ()
sys . exit (0)
time . sleep (0.0750)
self . n unchuk Remont e = False
"""
Calcule si la wiimote remonte
if self . w iimote Remont e == False and \
len ( self . wxt ) > 5 and \
np . abs ( self . wxt [ len ( self . wxt ) -1] - self . wxt [ len ( self . wxt ) -2]) < deltaX and \
self . wzt [ len ( self . wzt ) -2] - self . wzt [ len ( self . wzt ) -3] +\
self . wzt [ len ( self . wzt ) -3] - self . wzt [ len ( self . wzt ) -4] +\
self . wzt [ len ( self . wzt ) -4] - self . wzt [ len ( self . wzt ) -5] < - deltaZ :
"""
if self . w iimote Remont e == False and \
len ( self . wxt ) > 2 and \
np . abs ( self . wxt [ len ( self . wxt ) -1] - self . wxt [ len ( self . wxt ) -2]) < deltaX and \
self . wzt [ len ( self . wzt ) -1] < 140:
print " wiimote remontee "
self . w iimote Remont e = True
"""
calcule si le nunchuk remonte
"""
if self . cwiid . state . has_key ( ’ nunchuk ’) :
if self . n unchuk Remont e == False and \
len ( self . nxt ) > 5 and \
np . abs ( self . nxt [ len ( self . nxt ) -1] - self . nxt [ len ( self . nxt ) -2]) < deltaX
and \
np . abs ( self . nzt [ len ( self . nzt ) -1] - self . nzt [ len ( self . nzt ) -2]) and \
self . nzt [ len ( self . nzt ) -2] - self . nzt [ len ( self . nzt ) -3] +\
self . nzt [ len ( self . nzt ) -3] - self . nzt [ len ( self . nzt ) -4] +\
self . nzt [ len ( self . nzt ) -4] - self . nzt [ len ( self . nzt ) -5] < - deltaZ :
print " nunchuk remontee "
self . n unchuk Remont e = True
"""
Cette fonction detecte les sons et fonction a lance en mode " Star War " et "
Boite a Meuh "
Elle n ’ est lance que lorsque le bouton " home " a ete enclenche
Ainsi , lorsque le bouton A est enclenche on ouvre ou ferme le sabre laser .
Cette action enclenche ( ou arrete ) le mode Star Wars , qui calculera les
variations du sabre
Sur le bouton B , on enclenche les tirs laser
Une derniere variation se calcule si le mode " Star Wars " n ’ est pas active
Ces 3 actions differents ne sont pas compatible au meme moment .
"""
def autreSon ( self ) :
if self . cwiid . state [ ’ buttons ’] & cwiid . BTN_A :
14
sonStarWars = self . sonStarWars
if self . pid1 != os . getpid () :
os . kill ( self . pid1 , signal . SIGKILL )
self . pid1 = os . fork ()
if self . pid1 == 0:
if sonStarWars :
print " Eteignage "
os . kill ( self . pid2 , signal . SIGKILL )
self . l ireSon Fichie r ( worker . eteignageSW )
else :
print " Allumage "
self . l ireSon Fichie r ( worker . allumageSW )
sys . exit (0)
else :
self . sonStarWars = not ( self . sonStarWars )
os . waitpid ( self . pid1 , 0)
self . pid1 = os . getpid ()
elif self . cwiid . state [ ’ buttons ’] & cwiid . BTN_B :
if self . pid1 != os . getpid () :
os . kill ( self . pid1 , signal . SIGKILL )
self . pid1 = os . fork ()
if self . pid1 == 0:
print " Tir "
self . l ireSon Fichie r ( worker . tirSW )
sys . exit (0)
else :
os . waitpid ( self . pid1 , 0)
self . pid1 = os . getpid ()
if self . sonStarWars :
self . c a l c u l e r V a r i a t i o n S a b r e L a s e r ()
else :
self . c a l c u l e r V a r i a t i o n B o i t e M e u h ()
"""
Ici , selon les variations de la wiimote , on declenche un son different ( comme
un mouvement prolonge ) .
Tout au long de cette fonction , un son ambiant , representant celui du sabre
laser est diffuser en continue .
"""
def c a l c u l e r V a r i a t i o n S a b r e L a s e r ( self ) :
self . pid2 = os . fork ()
if self . pid2 == 0:
seuil = 50
if len ( self . wxt ) > 2 :
variation = np . abs ( self . wxt [ len ( self . wxt ) -1] - self . wxt [ len ( self . wxt )
-2]) +\
np . abs ( self . wyt [ len ( self . wyt ) -1] - self . wyt [ len ( self . wyt ) -2]) +\
np . abs ( self . wzt [ len ( self . wzt ) -1] - self . wzt [ len ( self . wzt ) -2])
if variation > 3* seuil :
self . l ireSon Fichie r ( worker . ventCourtSW )
elif variation > seuil :
self . l ireSon Fichie r ( worker . ventLongSW )
else :
self . l ireSon Fichie r ( worker . ambiantSW )
else :
self . l ireSon Fichie r ( worker . ambiantSW )
sys . exit (0)
else :
time . sleep (0.2)
"""
Cette fonction joue le son de boite a meuh lorsque la wiimote est tournee dans
le sens vertical , la tete en bas .
15
Mais lorsqu ’ elle remonte , pour imiter une vrai boite a meuh , le son se coupe
"""
def c a l c u l e r V a r i a t i o n B o i t e M e u h ( self ) :
# y en bas : 155 -156 : jouer le son
# y en haut : 103
borneSupY = 150
borneInfY = 107
if self . j ouerBo iteMeu h == True and \
len ( self . wyt ) > 2 and \
self . wyt [ len ( self . wyt ) -1] > borneSupY :
if self . pid1 != os . getpid () :
os . kill ( self . pid1 , signal . SIGKILL )
self . pid1 = os . fork ()
if self . pid1 == 0:
self . l ireSon Fichie r ( self . boiteMeuh )
sys . exit (0)
else :
self . j ouerBo iteMeu h = False
if self . j ouerBo iteMeu h == False and \
len ( self . wyt ) > 2 and \
self . wyt [ len ( self . wyt ) -1] < borneInfY :
if self . pid1 != os . getpid () :
os . kill ( self . pid1 , signal . SIGKILL )
self . j ouerBo iteMeu h = True
def wiiplot ( fig , w ) :
x = np . array ( w . wxt , dtype = np . int64 )
x = x -127 # Compense l ’ offset du capteur
y = np . array ( w . wyt , dtype = np . int64 )
y = y -127
z = np . array ( w . wzt , dtype = np . int64 )
z = z -127
print len ( x )
plt . clf ()
plt . s ub pl o ts _a d ju st ( hspace =.4)
# Plot time data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - plt . subplot (3 ,1 ,1)
plt . plot (x , "o - b " )
plt . grid ( " on " )
plt . xlabel ( ’n ’)
plt . ylabel ( ’x ’)
plt . title ( ’ Ac celero metres Wii ’)
plt . subplot (3 ,1 ,2)
plt . plot (y , "o - g " )
plt . grid ( " on " )
plt . xlabel ( ’n ’)
plt . ylabel ( ’y ’)
plt . subplot (3 ,1 ,3)
plt . plot (z , "o - r " )
plt . grid ( " on " )
plt . xlabel ( ’n ’)
plt . ylabel ( ’z ’)
plt . draw ()
"""
Fonction menu , qui donne le choix de configuration des manttes
"""
def menu () :
16
print " Entrer la lettre correspondant a votre configuration parmis les choix ci
- dessous "
print " a . Une wiimote "
print " b . Deux wiimote "
print " c . Une wiimote et un nunchuk "
choix = raw_input ( ’ Votre configuration : ’)
return choix
"""
Cette fonction traite le choix de configuration , en creant selon un objet wiimote ,
deux , ou un objet wiimote avec un nunchuk connecte
"""
def traitement ( choix = ’a ’) :
if choix == ’a ’:
print " Une wiimote "
print ’ place wiimote1 in discoverable mode ( press 1 and 2) ... ’
wiimote1 = cwiid . Wiimote ()
wiimote1 . led = 1
wiimote1 . rpt_mode = cwiid . RPT_ACC | cwiid . RPT_BTN
print ’ Wii discovered ... start recording ... ’
w1 = worker ( wiimote1 )
w1 . start ()
w1 . reset ()
plt . ion ()
elif choix == ’b ’:
print " Deux wiimote "
print ’ place wiimote1 in discoverable mode ( press 1 and 2) ... ’
wiimote1 = cwiid . Wiimote ()
wiimote1 . led = 1
wiimote1 . rpt_mode = cwiid . RPT_ACC | cwiid . RPT_BTN
print ’ Wii discovered ... start recording ... ’
print ’ place wiimote2 in discoverable mode ( press 1 and 2) ... ’
wiimote2 = cwiid . Wiimote ()
wiimote2 . led = 2
wiimote2 . rpt_mode = cwiid . RPT_ACC | cwiid . RPT_BTN
print ’ Wii discovered ... start recording ... ’
w1 = worker ( wiimote1 )
w2 = worker ( wiimote2 )
w1 . start ()
w2 . start ()
w1 . reset ()
w2 . reset ()
plt . ion ()
elif choix == ’c ’:
print " Une wiimote et un nunchuk "
print ’ place wiimote1 in discoverable mode ( press 1 and 2) ... ’
wiimote1 = cwiid . Wiimote ()
wiimote1 . led = 1
wiimote1 . rpt_mode = cwiid . RPT_NUNCHUK | cwiid . RPT_ACC | cwiid . RPT_BTN
while not ( wiimote1 . state . has_key ( ’ nunchuk ’) ) :
print " attente "
time . sleep (0.5)
print ’ Wii discovered ... start recording ... ’
w1 = worker ( wiimote1 )
w1 . start ()
w1 . reset ()
plt . ion ()
else :
print " Erreur , au moins une wiimote est requise pour ce programme "
"""
La fonction main lance simplement le menu et son traitement
"""
17
if __name__ == ’ __main__ ’:
choix = menu ()
traitement ( choix )
18