jeudi 17 décembre 2009

High-Tech : Robotique

Vu au gré de mes surfs :



Je suis tombé sous le charme : en plus de l'aspect kawai, la prouesse technologique n'est pas à occulter, l'effort d'intégration dans un si petit objet force le respect surtout quand c'est l'oeuvre d'un passionné :)

Sport : Méthode R2PH

Vous n'êtes pas sans savoir que je suis amateur de sport, en faite, de course à pied (après environ 13 ans de karaté).
Je traine sur le forum "course à pied" sur HFR ainsi que sur Athlète Endurance (bien que cela fait un moment que je n'y suis pas retourné).
Véronique Billat a récemment participé à un forum à Limoge, j'ai essayé tant bien que mal de trouver quelqu'un prêt à y aller avec moi ... en vain.
Bref, il se trouve qu'un des fondateurs du site Athlète Endurance (Jean Pierre Monciaux) a réussi à créer un partenariat avec la célèbre Véronique Billat !
Cela a déjà commencé à porter ses fruits et elle nous donne rdv le 02 janvier 2010 sur son site.
Pour ma part, rendez vous est pris !

lundi 30 novembre 2009

Humour : Les doigts ou la queue ?

Que dire ... rien, regardez d'abord :



Je précise que ce n'est pas un fake et que c'est réellement passé à la tv chinoise, le traducteur n'ayant pas vu la vidéo au moment de la traduction, le résultat est quelque peu ... original.
A noter que le traducteur a été viré, il explique tout sur son blog.

lundi 23 novembre 2009

Insolite : finger tutting

Le finder tutting, kezako ? Réponse, en vidéo ! (en plus ça rime ^_^ )

Humour : Sarkozy, aussi...

Encore une vidéo, celle-ci parodiant qui vous savez, assez bien faite je trouve :)

Insolite : c'est beau

Petite vidéo de danseurs qui savent ce que le mot synchro veut dire :

vendredi 13 novembre 2009

Musique : Thriller 8 bits mix

Si vous trainez sur mon blog (à moins que je monologue ? pas grave ), vous n'êtes pas sans savoir que la musique et le son en général tiennent une place importante dans mon temps libre.
C'est en surfant par hasard que je suis tombé sur cette vidéo : on y voit un dj remixer le légendaire tube du défunt roi de la pop, Mickael Jackson.
Le moins que l'on puisse dire c'est qu'il sait tripoter du sid et du lfo le petit !
C'est presque un sans faute (cf la fin) mais le remix est globalement plutôt bien géré, avec des patterns biens sentis, des montées/descentes au bon moment.
A noter qu'il n'en est pas à son coup d'essaie, je vous invite à visiter sa page MySpace.

Mangas : "petite" production indépendante

Une courte animation d'un petit studio qui a tout d'un grand tellement celle-ci est bluffante !

Humour : Surprise aux vestiaires

No comment

samedi 10 octobre 2009

Musique : Kamini

En avant première inter galactique, le dernier clip de Kamini :



Perso, j'ai bien aimé !
Fan, je suis faut dire

mardi 6 octobre 2009

dimanche 27 septembre 2009

High-Tech : Samsung Jet

Petit billet pour "tester" ce téléphone mobile que je possède depuis presque un mois.
Tout d'abord, il faut noter que je ne suis pas un kikoolol asv sms addict mais que je suis par contre un technophile, il faut donc comprendre que j'utilise mon téléphone, pour téléphoner mais que j'aime avoir un téléphone technologiquement en avance pour l'utiliser hors téléphonie, justement.
Je cherchais donc ce type de téléphone et ça n'a pas été une mince affaire : le choix est pléthorique et il faut jongler entre ses points (en cas de renouvellement) et/ou les forfaits qui font varier à la hausse ou à la baisse de façon non substantiel le prix du mobile.
Cela m'a donc amené vers le Samsung Jet.
Tout d'abord, c'est un téléphone tres compact, plutôt bien fini, son aspect est épuré mais inspire une certaine solidité, une fois dans la main.
Par contre, il est laqué (ou brossé), il laisse donc des traces, surtout sur son écran de 3.1" pouce.
D'ailleurs, parlons en de cet écran : bluffant ! Il est certes petit mais il est de type AMOLED, ce qui garantis une vivacité des couleurs et un contraste que peu de mobiles peuvent se vanter d'avoir.
Il est de plus moins énergivore et cela s'en ressent (nous verrons cela plus bas).
Côté technique : il est wifi, bluetooth, 3G+ (HSDPA), 5 mégapixels avec double flash, radio fm, compatible divx, gps, puce arm cortex 800mhz ... bref, de ce côté, il s'en sort haut la main.
En pratique maintenant. Le wifi fonctionne plutôt bien, je m'en sers pour surfer avec l'excellent navigateur intégré, basé sur le moteur de rendu Webkit (support rss, 5 onglets actifs, zoom in/out via l'écran très puissant), et le surf est agréable. Il est annoncé compatible flash mais aucun site ne m'a affiché la moindre animation, c'est un des griefs que je ferais à ce mobile.
Je n'ai pas testé le bluetooth mais il est EDR 2.1 donc stéréo mais connaissant cette technologie, faites attention au casque choisit, mieux vaut le commander sur le net (7j pour le retourner) car c'est souvent la loterie niveau compatibilité.
L'appareil photo est de très bonne facture, les images sont détaillé, pas floutées, il dispose apparemment d'un autofocus car je ne vois pas de blur lorsque les éléments bougent, de ce côté il peut réellement dépanner ceux qui n'ont pas de (leur) apn.
A noter qu'il dispose d'un détecteur de sourire (fonctionne bien !) et d'un logiciel de retouche photo.
D'ailleurs, le navigateur de photo est plutôt pas mal, cela se fait en glissant naturellement le doit de droite à gauche, les animations sont fluide et avec l'écran, on en prend plein les yeux.
Il prend en charge la vidéo, divx notamment en lecture ET écriture ! Perplexe, j'ai testé avec un de mes rips de 700mo que j'ai copié/collé, c'est passé sans le moindre soucis : vidéo fluide, aucune saccade, l'avance/retour se fait sans anicroche et il permet même de relancer la vidéo là où on l'a laissé.
Je n'ai pas testé l'encodage par contre mais bon j'imagine que ça pourra juste dépanner.
Ce mobile est aussi très axé social, il a en standard des widgets pour facebook, twitter et autre truc aussi inutile que TF1 (à mon sens) mais aussi très à la mode pour les kikoo lol.
D'ailleurs, ils sont pratiques, ces widgets, notamment ceux de google : google maps, gmail, google search, ça fonctionne pas trop mal, avec des ralentissement par contre pour google maps, en tout cas lorsqu'il met en cache pour la première fois l'endroit que vous visitez, après, ça va.
Il dispose d'un agenda simple et bien fait, synchronisable, d'ailleurs il support Exchange, ça, c'est plutôt rare, il faut en général se tourner vers les blackberry pour avoir cette possibilité.
Lors d'un appel ou de la réception, le téléphone propose les options adéquates (visio, clavier, etc ...), c'est très agréable et ça évite d'aller les chercher en pleine discussion.
Ah oui, une option qui m'a amusé : il est possible de simuler un appel téléphonique avec même la possibilité d'enregistrer une voix pour rendre cette simulation parfaite, parfait lors d'une réunion un peu longue ou quand on a envie d'aller voir ailleurs :p
Le Motion Gate permet de le secouer, ça permet, par exemple, de faire lecture/pause (en le tapotant deux fois de suite sur le dessus), un coup rapide de gauche au centre fera un retour arrière et l'inverse, lancera la musique suivante.
Le Media Gate 3D permet quant à lui d'afficher un cube et de passer d'une application en le secouant la aussi, les applications sont affichées différemment pour profiter de l'accélération 3D.
L'étiquette pause permet quand à elle de muter le téléphoner en tournant l'écran en direction du sol.
Bref, la partie logiciel est très agréable et n'a rien à envier à un iPhone, c'est dit.
Cependant, elle a un gros défaut : c'est un OS propriétaire et son avenir est lié au bon vouloir de Samsung qui le fera évoluer, ou pas.
Toutefois, il est compatible Java et en surfant sur le net vous devriez trouver une méthode pour installer des applications sans trop de soucis (Samsung ayant bloqué cette possibilité).
Enfin, l'autonomie est très bonne, comptez 4/5 jours pour une utilisation standard, il tient 7 jours de mon côté (téléphone, un peu de radio/mp3).
A noter que j'ai pris un forfait chez Orange qui a bien pourri l'OS, j'invite tout le monde à passer au flash officiel, d'autant plus qu'Orange à supprimé la suite Google ...
Je n'ai pas testé le GPS mais je sais que route 66 est compatible et c'est une application qui fonctionne bien.
Ce test n'est pas exhaustif et permet de conclure en disant que c'est un téléphone qui se suffit à lui même, il permet de combler 95% des besoins de n'importe quel utilisateur, pour les geeks avancé apprentis codeurs ou tous ceux qui ne jurent que par des centaines d'application, l'iPhone et autres HTC Magic sont la.

Quelques liens utiles :

Site officiel Samsung Jet
Page Principale de DarkForest
Forum de DarkForest
Forum HFR
Test LesNumeriques

Vidéo : Voltage

Encore une vidéo mais cette fois-ci, je l'ai aimé pour son aspect artistique et surtout parce que ça parle forcément à tous ceux qui sont de près ou de loin dans le secteur du traitement du signal :)

Voltage from Bam Studio on Vimeo.

Humour : d'hôtesse

Une vidéo que j'ai trouvé amusante :

jeudi 13 août 2009

Programmation : VMWare rachète SpringSource

ArsTechnica nous fait part d'une brève importante mais que peu de sites relaye, à savoir le rachat de la société SpringSource par VMWare.
SpringSource est la société qui est, entre autre, derrière le framework Spring, utilisé dans le monde Java et dans le monde professionnel.
VMWare est une société qui propose des produits à destination de la virtualisation.
Maintenant, quel est le rapport entre les deux ? Pourquoi une société comme VMWare lorgnerais vers un framework java ? Tout réside dans le mot service.
En effet, VMWare a une vision a long terme et toujours dans une logique de cloud computing, la société souhaite proposer la virtualisation sous forme de service, en utilisant un framework, la société souhaite proposer tout un ensemble de fonctionnalité permettant de paramétrer, modifier en temps réel, déployer ses machines virtuelles pour ainsi les intégrer dans le parc de façon totalement automatisée et transparente.
C'est un enjeux capital à l'heure où de nombreux décideurs du monde IT (supports notamment) ont intégré la virtualisation dans le déploiement de leur parc physique.
Nombreux sont ceux qui pestent sur le côté monolithique voire risqué quant à déployer une VM pour des données critiques, le fait d'avoir la main totale sur le déploiement (entre autre) devrait leur faire changer d'opinion.
Il est à noter que VMWare proposera ses produits sous forme de service via le travail effectué via Spring mais permettra aussi à n'importe quel autre société de proposer sa propre solution, la société diffusera une API rendra cela possible.
Je pense que VMWare a vraiement fait le bon choix, aujourd'hui, tout tend vers les services, le succès des SOA est la pou r le montrer :)

lundi 6 juillet 2009

Jeux Vidéos : Blizzard et le marketing

Quelle ne fut pas ma déception lorsque j'ai appris que Blizzard, célèbre développeur de jeux aux millions de ventes comme la série des Diablo, Warcraft et Starcraft, n'allait pas incorporer le jeux en LAN (réseau local) !
Les LAN et moi, c'est une longue histoire, commencée en 1996 alors qu'aucune salle réseau existait encore (j'avais projeté d'ouvrir une franchise ... j'aurais dû, j'aurai eu le jackpot ^^ ) avec de beaux câble DB25 et mon super 486dx et bien sûr Doom.
C'était ultra confidentiel, à tel point qu'on en faisait dans une cave après avoir judicieusement raccordé le circuit électrique de l'immeuble à notre cave tout en faisant passer un câble réseau de 200m par le toit (5 étages quand même).
J'ai eu ma période nolife pendant 4 bonnes années avec 2/3 lans par semaine, jusqu'à créer une association loi 1901 de jeux en réseau (en 1997) pour en fait n'avoir qu'une salle plus grande et officielle, cette fois.
Été comme hiver, rien ne pouvait nous arrêter, on avait les doigts gelés, emmitouflés dans nos couettes, on jouait quand même.
Bref on étais quand même hardcore, atteints diront certains mais n'est-ce pas la la définition d'une passion ? ;)
Tout ça pour dire que Blizzard me déçoit, j'avais pour coutume de dire "un jeux Blizzard, ça ne se pirate pas, ça s'achète", du coup, ça sera ni l'un ni l'autre.

mardi 30 juin 2009

Sport : nouvelles chaussures

A l'image de ce billet, les soldes sont la et je n'ai pas pu résister :


Je les ai acheté tout à l'heure donc pas encore essayé. (66 € au lieu de 110€)
Pourquoi une nouvelle paire ?
Tout simplement parce que j'en ai que deux dont une qui a facile 2000 kms avec la gomme de la semelle bien mangée, mon autre paire me sert plutôt pour des sorties longues, il me fallait donc une nouvelle paire, plutôt axé dynamisme pour les fractionnées.
J'espère avoir fait le bon choix, n'hésitez pas à me le dire dans les commentaires :p

Emulation : VirtualBox 3.0.0

Voila, c'est fait, ce virtualiseur vient de sortir en version (majeure) 3.0.
Majeure car, et c'est à la mode dans ce milieu, elle offre le support de la 3D !
Sisi, on peut jouer à des jeux (DirectX 9 max) dans une machine virtuelle et ce, de manière tout à fait convenable.
Outre cet ajout majeur, il ne risque pas de toucher la vraie cible de ces outils : les admins et autres supports techniques.
La, on peut virtualiser jusqu'à 32 CPU, binder les sockets pour une interface réseaux spécifique, une amélioration du boot PXE, le RDP de Windows 7 ... la liste complète est consultable ici, pour le téléchargement, c'est par la.

jeudi 21 mai 2009

Musique : Playing For Change

Je ne sais pas si les plus surfeurs d'entre vous connaissent ce site mais c'est juste un must have : Playing For Change.
L'idée est simple : aller à la rencontre d'inconnus, tout autour du monde, souvent ils s'agit de ces gens que l'on rencontre dans le métro, les gares ou en plein centre ville avec leur guitare ou juste leur voix.
Vient l'idée d'aller à leur rencontre avec pour objectif de produire des musiques prônant la paix via leurs musiques en mixant l'interprétation de chacun, individuellement, les vidéos vous parleront plus.
Ma foi, je doit dire que le but est "quelque peu" atteint, deux vidéos prises au hasard car elles sont toutes ... magnifiques.



mardi 19 mai 2009

Programmation : 2ème partie, de l'importance de l'optimisation

Suite de ce billet, on va rentrer dans le vif du sujet.
Je ne vais pas détailler l'algorithme mais le code doit calculer les 16 points permettant de calculer l'amplitude finale, cela consiste donc à multiplier chaque point source par l'échantillon et à multiplier chaque point de destination par le sample, à ce stade, nous avons les deux amplitudes (source et destination), il ne reste plus qu'à calculer l'amplitude qui consiste à obtenir la distance entre ces deux points (+ partie fractionnelle).
Voici le code original, en PureBasic, oui je sais, inconnu au bataillon tout ça mais peu importe, n'importe quel programmeur devrait comprendre le code, plutôt simple :

#FP_SHIFT = 15

; init sinc table
SAMPLE_init_sinc_table()

; init sample data
*sample_data = AllocateMemory(16 * 2)

; init mix buffer (4 samples)
; LR - LR - LR - LR
*mix_buffer = AllocateMemory(8 * SizeOf(Long))

; alimentation de données bidon
PokeW(*sample_data + 0, 10)
PokeW(*sample_data + 2, 20)
PokeW(*sample_data + 4, 30)
PokeW(*sample_data + 6, 40)
PokeW(*sample_data + 8, 50)
PokeW(*sample_data + 10, 60)
PokeW(*sample_data + 12, 70)
PokeW(*sample_data + 14, 80)

PokeW(*sample_data + 16, 90)
PokeW(*sample_data + 18, 100)
PokeW(*sample_data + 20, 110)
PokeW(*sample_data + 22, 120)
PokeW(*sample_data + 24, 130)
PokeW(*sample_data + 26, 140)
PokeW(*sample_data + 28, 150)
PokeW(*sample_data + 30, 160)


size_of_word = SizeOf(Word)
table_idx = 0
sample_idx = 0
offset = 0
left_gain = 2408
right_gain = 5156

start0 = GetTickCount_()
For i = 0 To 10000000

While offset < 8

*sinc_table_ptr = *sinc_table + ( ( table_idx + 0 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 0) * size_of_word )
a1 = (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 16) * size_of_word )
a2 = (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 1 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 1) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 17) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 2 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 2) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 18) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 3 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 3) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 19) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 4 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 4) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 20) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 5 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 5) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 21) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 6 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 6) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 22) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 7 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 7) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 23) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 8 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 8) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 24) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 9 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 9) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 25) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 10) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 10) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 26) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 11) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 11) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 27) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 12) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 12) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 28) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 13) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 13) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 29) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 14) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 14) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 30) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

*sinc_table_ptr = *sinc_table + ( ( table_idx + 15) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 15) * size_of_word )
a1 + (*sinc_table_ptr\w * *sample_data_ptr\w)
*sinc_table_ptr = *sinc_table + ( ( table_idx + 31) * size_of_word )
a2 + (*sinc_table_ptr\w * *sample_data_ptr\w)

a1 >> #FP_SHIFT
a2 >> #FP_SHIFT

; SIMPLIFICATION du code (code bidon, ne fonctionne pas)
amplitude = a1 + a2

*mix_buffer_ptr = *mix_buffer + (offset * SizeOf(Long))
newsample = (amplitude * left_gain) >> #FP_SHIFT
*mix_buffer_ptr\l + newsample

*mix_buffer_ptr = *mix_buffer + ((offset + 1) * SizeOf(Long))
newsample = (amplitude * right_gain) >> #FP_SHIFT
*mix_buffer_ptr\l + newsample

offset + size_of_word

; fake sinc table_idx
table_idx + 1

;Debug "SINC_NO_SSE:: A1 = " + Str(a1) + " A2 = " + Str(a2)

Wend

offset = 0
table_idx = 0
sample_idx = 0
Next i
end0 = GetTickCount_()

; result of mixing
amp1 = PeekL(*mix_buffer + 0 * SizeOf(long) )
amp2 = PeekL(*mix_buffer + 1 * SizeOf(long) )
amp3 = PeekL(*mix_buffer + 2 * SizeOf(long) )
amp4 = PeekL(*mix_buffer + 3 * SizeOf(long) )
amp5 = PeekL(*mix_buffer + 4 * SizeOf(long) )
amp6 = PeekL(*mix_buffer + 5 * SizeOf(long) )
amp7 = PeekL(*mix_buffer + 6 * SizeOf(long) )
amp8 = PeekL(*mix_buffer + 7 * SizeOf(long) )

Debug "SINC_NO_SSE:: SSE_CALC amp1 = " + Str(amp1) + " amp2 = " + Str(amp2) + " amp3 = " + Str(amp3) + " amp4 = " + Str(amp4)
Debug "SINC_NO_SSE:: SSE_CALC amp5 = " + Str(amp5) + " amp6 = " + Str(amp6) + " amp7 = " + Str(amp7) + " amp8 = " + Str(amp8)



Explication :
- initialisation d'un tableau contenant les points pré calculés pour des échantillons sur 16 bits ( SAMPLE_init_sinc_table() ),
- allocation d'un tampon contenant les échantillons en entrée (8 échantillons car un échantillons occupe 2 octets * 2 car il est stéréo au format LR (Left - Right) ),
- allocation d'un tampon en sortie au format entier pour stocker pour un entier, l'échantillon stéréo donc un int contient deux shorts (LR),
- alimentation via des données bidons (les PokeW(*sample_data + 0, 10) ... ),
- initialisation de différentes valeurs pour le test,
- puis vient la partie critique, on boucle 10000000 (pour le bench), à chaque itération, nous bouclons 8 fois pour récupérer 2*8 shorts d'échantillons qui seront stockés dans notre tampons de mixage, pour chaque itération, nous calculons le point source et destination, je le scale sur 16 bits (-1 pour le bit de signe) et je stocke le tout dans le mélangeur.

Un gros pâte pour finalement pas grand chose.
Maintenant, voyons ce que ça donnerais en SSE2 :

Procedure.l PB_sse2_mul_add(*p1.Word, *p2.Word, size.l)
Protected *dest_buffer_ptr.Long
Protected idx.l, size_of_elements = size / 8

*dest_buffer_ptr = @dest_buffer()

!MOV esi, [p.p_p1]
!MOV edi, [p.p_p2]
!MOV edx, [p.p_dest_buffer_ptr]
!XOR ecx, ecx
!PXOR xmm4, xmm4

For idx = 0 To size_of_elements - 1
!MOVUPS xmm0, [esi+ecx] ; +16
!MOVUPS xmm1, [esi+ecx] ; +16

!MOVUPS xmm2, [edi+ecx] ; +16

!PMULLW xmm0, xmm2
!PMULHW xmm1, xmm2

!MOVUPS xmm3, xmm0 ; copy orig xmm0

!PUNPCKLWD xmm0, xmm1 ; xmm0 --> loword (this is why it is was copied :p )
!PUNPCKHWD xmm3, xmm1

!PADDD xmm4, xmm0
!PADDD xmm4, xmm3

!MOVUPS [edx], xmm4

!ADD ecx, 16
Next idx

result = PeekL(*dest_buffer_ptr) + PeekL(*dest_buffer_ptr+4) + PeekL(*dest_buffer_ptr+8) + PeekL(*dest_buffer_ptr+12)

ProcedureReturn result
EndProcedure

;- calc amplitude 0
*sinc_table_ptr = *sinc_table + ( ( table_idx + 0 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 0) * size_of_word )

a1 = PB_sse2_mul_add(*sinc_table_ptr, *sample_data_ptr, 16)
a2 = PB_sse2_mul_add(*sinc_table_ptr+32, *sample_data_ptr, 16)

a1 >> #FP_SHIFT
a2 >> #FP_SHIFT

calc_amp(0) = a1 + a2

; fake sinc table_idx
table_idx + 1

Debug "SINC_SSE:: A1 = " + Str(a1) + " A2 = " + Str(a2)

;- calc amplitude 1
*sinc_table_ptr = *sinc_table + ( ( table_idx + 0 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 0) * size_of_word )

a1 = PB_sse2_mul_add(*sinc_table_ptr, *sample_data_ptr, 16)
a2 = PB_sse2_mul_add(*sinc_table_ptr+32, *sample_data_ptr, 16)

a1 >> #FP_SHIFT
a2 >> #FP_SHIFT

calc_amp(1) = a1 + a2

; fake sinc table_idx
table_idx + 1

;- calc amplitude 2
*sinc_table_ptr = *sinc_table + ( ( table_idx + 0 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 0) * size_of_word )

a1 = PB_sse2_mul_add(*sinc_table_ptr, *sample_data_ptr, 16)
a2 = PB_sse2_mul_add(*sinc_table_ptr+32, *sample_data_ptr, 16)

a1 >> #FP_SHIFT
a2 >> #FP_SHIFT

calc_amp(2) = a1 + a2

; fake sinc table_idx
table_idx + 1

;- calc amplitude 3
*sinc_table_ptr = *sinc_table + ( ( table_idx + 0 ) * size_of_word )
*sample_data_ptr = *sample_data + ( ( sample_idx + 0) * size_of_word )

a1 = PB_sse2_mul_add(*sinc_table_ptr, *sample_data_ptr, 16)
a2 = PB_sse2_mul_add(*sinc_table_ptr+32, *sample_data_ptr, 16)

a1 >> #FP_SHIFT
a2 >> #FP_SHIFT

calc_amp(3) = a1 + a2

; fake sinc table_idx
table_idx + 1

*calc_amp_ptr = @calc_amp(0)
*mix_buffer_ptr = *mix_buffer + (0 * SizeOf(Long))
*left_gain_ptr = @left_gain
*right_gain_ptr = @right_gain

; sse mixing

; L - L - L - L
; 159 - 139 - 119 - 99
;* 2048 - 2048 - 2048 - 2048
; ---- ----- ----- -----
;325632 284672 243712 202752

; R - R - R - R
; 159 - 139 - 119 - 99
;* 5156 - 5156 - 5156 - 5156
; ---- ----- ----- -----
; 819804 716684 613564 510444

start1 = GetTickCount_()
For i = 0 To 10000000

!MOV esi, [p_calc_amp_ptr]
!MOV edi, [p_mix_buffer_ptr]
!MOV ebx, [p_left_gain_ptr]
!MOV edx, [p_right_gain_ptr]
!PXOR xmm0, xmm0
; !PXOR xmm1, xmm1
!PXOR xmm2, xmm2
!PXOR xmm3, xmm3
!PXOR xmm4, xmm4
; !PXOR xmm5, xmm5

; store
!MOVUPS xmm0, [esi] ; amp0 - amp1 - amp2 - amp3 (LLLL)
!MOVUPS xmm4, xmm0 ; amp0 - amp1 - amp2 - amp3 (RRRR)
!MOVUPS xmm1, [edi] ; sample0 - sample1 - sample2 - sample3
!MOVUPS xmm5, [edi+16] ; sample4 - sample5 - sample6 - sample7
!MOVUPS xmm2, [ebx] ; ? - ? - ? - left_gain
!MOVUPS xmm3, [edx] ; ? - ? - ? - right_gain

; prepare shift
!PSHUFD xmm2, xmm2, 00b ; left_gain - left_gain - left_gain - left_gain
!PSHUFD xmm3, xmm3, 00b ; right_gain - right_gain - right_gain - right_gain

; calc amplitude
!cvtdq2ps xmm2, xmm2 ; int --> single
!cvtdq2ps xmm3, xmm3 ; int --> single

!cvtdq2ps xmm0, xmm0 ; int --> single
!cvtdq2ps xmm4, xmm4 ; int --> single

; perform 4 singles mul (LLLL)
!mulps xmm0, xmm2 ; amp0*left_gain - amp1*left_gain - amp2*left_gain - amp3*left_gain (create LLLL sample)
; perform 4 singles mul (RRRR)
!mulps xmm4, xmm3 ; amp0*right_gain - amp1*right_gain - amp2*right_gain - amp3*right_gain (create RRRR sample)

!cvtps2dq xmm0, xmm0
!cvtps2dq xmm4, xmm4

; calc fractional bits
!PSRAD xmm0, 15 ; amp0 >> #FP_SHIFT - amp1 >> #FP_SHIFT - amp2 >> #FP_SHIFT - amp3 >> #FP_SHIFT (LLLL)
!PSRAD xmm4, 15 ; amp0 >> #FP_SHIFT - amp1 >> #FP_SHIFT - amp2 >> #FP_SHIFT - amp3 >> #FP_SHIFT (RRRR)

; save orig values (for low 32 bits word)
!MOVUPS xmm2, xmm0
!MOVUPS xmm3, xmm4

; unpack orig 32 bits low words to saved 32 bits high words (LRLR for 1st sample)
!UNPCKLPS xmm0, xmm4 ; LRLR --> xmm0 (2 samples)
; unpack orig 32 bits high words to saved 32 bits low words (LRLR for 2nd sample)
!UNPCKHPS xmm2, xmm3 ; LRLR --> xmm2 (2 samples)

; mix result : 2 samples mixed at a time
!PADDD xmm1, xmm0
!PADDD xmm5, xmm2

!MOVUPS [edi], xmm1
!MOVUPS [edi+16], xmm5

Next i
end1 = GetTickCount_()

; result of mixing
amp1 = PeekL(*mix_buffer + 0 * SizeOf(long) )
amp2 = PeekL(*mix_buffer + 1 * SizeOf(long) )
amp3 = PeekL(*mix_buffer + 2 * SizeOf(long) )
amp4 = PeekL(*mix_buffer + 3 * SizeOf(long) )
amp5 = PeekL(*mix_buffer + 4 * SizeOf(long) )
amp6 = PeekL(*mix_buffer + 5 * SizeOf(long) )
amp7 = PeekL(*mix_buffer + 6 * SizeOf(long) )
amp8 = PeekL(*mix_buffer + 7 * SizeOf(long) )

Debug "SINC_SSE:: SSE_CALC amp1 = " + Str(amp1) + " amp2 = " + Str(amp2) + " amp3 = " + Str(amp3) + " amp4 = " + Str(amp4)
Debug "SINC_SSE:: SSE_CALC amp5 = " + Str(amp5) + " amp6 = " + Str(amp6) + " amp7 = " + Str(amp7) + " amp8 = " + Str(amp8)


Désolé pour les commentaires mais qu'est ce que cela signifie :
- 1ère différence : c'est LA clef de notre optimisation, on voit que je calcule 4 amplitude en appelant 4 fois la procédure PB_sse2_mul_add(), celle-ci me calcule la partie que j'ai mis en gras plus haut. Cela veut dire que, contrairement au code original, je ne calcule pas qu'une amplitude par itération mais 4 simultanément,
- 2ème différence : je stockais un échantillon au format LR, la, vu que j'ai calculé 4 amplitudes, j'en stocke 4 par itération au format LRLR-LRLR au lieu de LR ... tout court !
- ... et c'est tout !

Mais ces deux simples différences sont éloquentes :
- code PureBasic : 6520 ms en moyenne,
- code SSE2 : 170 ms en moyenne.

Soit 38x plus rapide, rien que ça ! Cela ne se voit pas que dans les benchs mais aussi dans le taux d'occupation cpu : j'oscille entre 2 à 5% (en pique), cela peut sembler encore beaucoup mais c'est tout de même deux fois moins gourmand, objectif réussi :)
Je vous laisse zieuter le code, n'oubliez pas google, c'est grâce à lui que je m'en suis sortie mais je reste disponible pour toute aide que je pourrais apporter :)

Programmation : 1ère partie, de l'importance de l'optimisation

Pas de billet pour annoncer mon come-back mais restons efficace et pour l'annoncer, quoi de mieux qu'un vrai sujet de fond ?
Ici, il s'agira de l'optimisation en programmation, en deux parties histoire de pas avoir un gros pâté.
En effet, à l'heure actuelle, de nombreux langages existent, tous de plus en plus de haut niveau, ayant un niveau d'abstraction, certes on ne s'occupe plus que de l'essentiel mais de fait, on s'éloigne aussi de plus en plus de la machine et donc de sa logique : java, .net, ruby & co n'en sont que quelques exemples.
Dès lors, les programmeurs ont oublié qu'on pouvait optimiser son code, si si, je le vois tous les jours au boulot, nombreux sont ceux qui ne font qu'utiliser tel et tel framework, hop un tour dans la doc, ok, j'utilise ça pour faire ça etc ... mais personne (ou rares) sont les personnes prenant le temps de la réflexion en se disant si son code est vraiment optimisé.
Si j'en parle c'est que j'ai été confronté à cette problématique.
Je code en ce moment une bibliothèque permettant de décoder de la musique au format soundtrack (mod/xm/s3m & co), il y a une partie qui s'occupe de l'interpolation des échantillons, histoire d'"améliorer" le son (ce format induit souvent ce qu'on appel des "clicks & pops" autrement dit des bruits statiques).
J'utilise différents algorithmes ("au plus proche", "linéaire", "cubic spline" et "fir sinc") et c'est ce dernier, très couteux en cpu (16 points sont calculés pour un échantillon) qui m'a fait tiqué.
En effet, j'ai tout bêtement lancé le gestionnaire des tâches pour constater que le cpu oscillait entre 2 et ... 12% !
Inconcevable pour moi, j'ai tout de même un Q9550@3.4 ghz, j'ose imaginer ce que ça donnerais sur un mono core (même si mon code n'est pas optimisé multi-core) ou avec un cpu @1ghz (oui, je me préoccupe de ces machines :) ).
Vient le temps de la réflexion : comment faire pour optimiser ce fameux code ?
Ca a été vite vu car il n'y a pas 30 000 façon de le faire :
- "penser" cpu : c'est à dire arranger son code pour faire en sorte d'être dans la logique de traitement du cpu (exemple : micro fusion, boucle déroulée, prefetch compliancy ...)
- utiliser le SIMD : j'ai déjà lu pas mal de sujer/code à ce sujet mais je ne l'ai jamais réellement utilisé, d'autant plus que je suis loin d'être un guru en assembleur.

N'écoutant que mon courage, la solution la plus viable à mon niveau est ... la seconde ! Oui, j'aime bien les challenges :p