Jouer un son en background (WinRT XAML)

by Nicolas Calvi 22. septembre 2012 19:22

Récemment je me suis confronté à un problème étonnant sur une application WinRT XAML. Je voulais jouer un son mais pas à partir d'une définition dans mon XAML, mais plutôt en code behind. 

J'ai donc cherché sur internet comment faire et force est de constater que la seule solution sans aller à créer un interop DirectSound, c'est de passer par le MediaElement. Cependant, passer par ce contrôle n'a pas été aussi simple qu'il n'y parait.

Déjà la première chose à savoir et qu'il m'a fait perdre un temps infini, c'est que le contrôle MediaElement NE GERE PAS LES WAV. Aussi étonnant que cela puisse paraître, il n'arrive pas gérer des WAVs, ou en tout cas ceux que je lui donnais, je les ai pourtant vérifié en les lisant avec différents lecteurs et le fichier n'avait aucun soucis. Dans notre cas il faudra donc passer par des MP3, donc ne vous faite pas avoir !

Ensuite, pour pouvoir jouer les sons de façon simple et de pouvoir en lancer le même fichier plusieurs fois, j'ai donc créé une classe qui permet de gérer ça de façon transparent. Cette classe n'a besoin que du chemin du fichier dans les ressources de l'application et de l'instance d'un Panel (GridCanvasPanel, peu importe) afin de pouvoir stocker son instance dans un arbre visuel. En effet, le MediaElement a besoin de se trouver dans l'arbre visuel pour fonctionner. Cela n'est pas étonnant car à la base c'est un contrôle XAML visuel.

Le principe de cette classe et quand on lui invoque la fonction Play(), c'est de créer un MediaElement, de lui affecter le fichier, l'ajouter dans l'arbre visuel, jouer le son et quand celui-ci est fini, retirer l'instance de ce MediaElement de l'arbre visuel. Simple mais efficace.

Vous pouvez télécharger cette classe via ce lien : SoundItem.cs (3,73 kb)

Voici le code source de cette classe :

using System;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

namespace MonApplication
{
    /// <summary>
    /// Représente un son a jouer avec sa gestion
    /// </summary>
    public class SoundItem
    {
        #region Propriétés

        /// <summary>
        /// Obtient la racine de l'arbre visuel que l'on va utiliser pour stocker nos MediaElements
        /// </summary>
        public Panel Root
        {
            get;
            private set;
        }

        /// <summary>
        /// Obtient l'URI associé au son
        /// </summary>
        public Uri Uri
        {
            get;
            private set;
        }

        #endregion


        #region Constructeur

        /// <summary>
        /// Constructeur de la classe
        /// </summary>
        /// <param name="root">Racine de l'arbre visuel que l'on va utiliser pour stocker nos MediaElements</param>
        /// <param name="filename">Fichier son de référence</param>
        public SoundItem(string filename, Panel root)
        {
            this.Root = root;
            this.Uri = new Uri("ms-appx:/" + filename);
        }

        #endregion

        #region Fonctions privées

        /// <summary>
        /// Joue le son
        /// </summary>
        public void Play()
        {
            // Création du MediaElement

            MediaElement sound = new MediaElement();
            sound.AutoPlay = false;
            sound.AudioCategory = AudioCategory.ForegroundOnlyMedia;
            sound.MediaOpened += this.OnMediaOpened;
            sound.MediaFailed += this.OnMediaFailed;
            sound.MediaEnded += this.OnMediaEnded;

            //  Ajour à l'arbre visuel

            this.Root.Children.Add(sound);

            // Chargement du son

            sound.Source = this.Uri;
        }

        #endregion

        #region Fonctions privées

        /// <summary>
        /// Se produit sur la fin de lecture d'un son
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void OnMediaEnded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            MediaElement sound = (MediaElement)sender;

            // On retire les handlers

            sound.MediaOpened -= this.OnMediaOpened;
            sound.MediaFailed -= this.OnMediaFailed;
            sound.MediaEnded -= this.OnMediaEnded;

            // Suppression de l'arbre visuel

            this.Root.Children.Remove(sound);
        }

        /// <summary>
        /// Se produit sur l'échec d'ouverture du son
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void OnMediaFailed(object sender, Windows.UI.Xaml.ExceptionRoutedEventArgs e)
        {
            MediaElement sound = (MediaElement)sender;

            // On retire les handlers

            sound.MediaOpened -= this.OnMediaOpened;
            sound.MediaFailed -= this.OnMediaFailed;
            sound.MediaEnded -= this.OnMediaEnded;

            // Suppression de l'arbre visuel

            this.Root.Children.Remove(sound);
        }

        /// <summary>
        /// Se produit sur la réussite de lecture du son
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void OnMediaOpened(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            MediaElement sound = (MediaElement)sender;

            // On joue le son

            sound.Play();
        }

        #endregion
    }
}

Si vous avez des questions sur le fonctionnement cette classe ou sur cet article, n'hésitez pas à me demander.

Installation d’un programme sur la Samsung SUR40

by Nicolas Calvi 10. juillet 2012 16:21

Pour installer une application sur la table Samsung SUR40 with Microsoft PixelSense, il faut suivre les étapes listées ci-dessous, pour tout complément d’information, vous pouvez  consulter la documentation officielle à cette adresse : http://msdn.microsoft.com/en-us/library/ff727836

1. Récupérer les exécutables

Pour installer une application vous pouvez déposer l’ensemble des Assemblies dans un répertoire au choix du système (il faut juste que la table possède les droits de lecture sur ces fichiers). Libre à vous d’organiser l’emplacement de stockage de vos applications.

Il est a noté  que les applications doivent être réalisées en WPF avec le SDK Surface 2 ou en XNA 4 avec les extensions du SDK Surface 2.

2. XML de configuration

Dans tous les projets pour Samsung SUR40, il faut définir un XML de définition du projet (si vous créez un projet avec le Surface SDK, ce fichier est automatiquement généré dans la solution sous la forme <nom application>.xml). 

Ce fichier XML contient les informations qui seront affichées dans le Shell Surface (Titre, description, miniature, etc.), mais aussi le chemin de l’exécutable de l’application. Voici un exemple de fichier de configuration :

<?xml version="1.0" encoding="utf-8"?>
<ss:ApplicationInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ss="http://schemas.microsoft.com/Surface/2007/ApplicationMetadata">
  <Application>
    <Title>Mon application</Title>
    <Description>Une application qui permet de faire des choses</Description>
    <ExecutableFile>MonExecutalbe.exe</ExecutableFile>
    <Arguments>
    </Arguments>
    <IconImageFile>Shell\icon.png</IconImageFile>
  </Application>
</ss:ApplicationInfo>

Ce fichier peut se trouver n’importe où, mais il est recommandé de le placer sur la racine où se trouve votre exécutable. Ensuite, à l’intérieur de ce fichier de configuration, les chemins d’accès (exécutable, icones) se font par rapport au répertoire où se trouve le fichier. Si vous voulez accéder à une ressource placée autre part sur votre disque, il faudra écrire le chemin complet d’accès à ce fichier. Pour tout complément d’information sur ce que peut contenir ce fichier, je vous conseille d’aller à cette adresse : http://msdn.microsoft.com/en-us/library/ff727761

3. Placer le fichier XML

 Une fois que vous avez posé votre application dans un répertoire et que vous avez le fichier XML de configuration, créez un raccourci de celui-ci (le fichier XML). Il faut ensuite mettre le raccourci du fichier XML dans le répertoire des applications Surface. Ce répertoire ce trouve habituellement à cet emplacement :

C:\ProgramData\Microsoft\Surface\v2.0\Programs

Ce n’est que si votre raccourci du fichier de configuration XML placé dans ce répertoire qu’il sera possible de gérer vos applications Surface sur la table Samsung SUR40.

Il est important de noter qu’il faut impérativement placer un raccourci du fichier XML dans le répertoire des applications, et non le fichier lui-même, si vous mettez le fichier lui-même, il ne sera pas pris en compte.

4. Gérer ses applications

Maintenant que vos raccourcis sont dans le répertoire des applications, il vous suffit de lancer l’utilitaire de gestion de la table Samsung SUR40, le « Surface Config Editor ».

 

Dans cette application on peut paramétrer les applications (fichier de configuration XML) qui seront actives dans le Shell ainsi que leur ordre dans celui-ci, c’est très simple.

Une fois validé, vous n’avez plus qu’à lancer le Shell Surface et voilà votre application qui apparait. Si d’une manière ou d’une autre, il y a une erreur dans votre fichier de configuration XML, l’application ne sera juste pas affichée dans le Shell, mais cela ne l’empêchera pas de se lancer.

 
Voilà c’est à peu près tout. Pour savoir comment lancer une application en mode « Single » ou pour tout complément d’information, il vous suffit d’aller consulter le site de référence Surface (http://msdn.microsoft.com/en-us/library/ff727836).

Easy Shopping disponible !

by Nicolas Calvi 27. juin 2012 10:25

Je viens de publier sur le Marketplace Windows Phone 7, une application de liste de course nommé Easy Shopping. J'ai réalisé cette application avec une autre MVP Surface et Designer Industriel à savoir Johanna Rowe. Nous avons créé cette application tout d'abord pour répondre à un besoin personnel, en effet nous n'avions pas trouvé d'application de liste de course qui nous satisfasse. Du coup, autant développer la nôtre !

Nous l'avons réalisée avec la même rigueur et le même processus de développement que nous utilisons en entreprise pour développer des applications NUI. Le focus a été mis sur la simplicité et l'expérience utilisateur. Nous n'avons par exemple pas mis de lecteur de code barre, car nous pensons qu'une liste de course se fait avant les courses et pas pendant, nous n'avons donc pas les codes barre sous la main.

Nous avons aussi ajouté une fonctionnalité qui nous parait intéressante, à savoir le fait de créer des recettes (avec une liste d'ingrédient) et de pouvoir d'un touch l'importer dans sa liste courante. On peut aussi sauvegarder une liste de course pour la réimporter par la suite, très utiles si on a des récurrences dans la saisie. 

Je vous invite donc à la télécharger, elle est gratuite et n'hésitez pas à me faire des retours !

PixelSense et Surface sont dans un bateau

by Nicolas Calvi 19. juin 2012 13:58

Il y a des moment dans la vie qui sont charnières ! Microsoft vient d'en vivre un hier soir à 00h30 heure de Paris avec l'annonce de sa première tablette Windows 8 fait maison.

J'ai le plaisir de vous présenter "Surface" !

Et oui, vous avez bien vue ! Une tablette nommé Surface. En effet c'est assez déroutant, mais avant de vous donner les implications que cela va avoir dans la dénomination des produits, voici quelques informations intéressantes sur cette nouvelle "Surface".

Il va en exister deux versions, une version dite "Windows RT" qui sera a mon sens a destination d'un usage plus casual à l'instar de l'iPad. Mais il y aura aussi une version dite "Windows 8 Pro" qui elle sera a destination des développeurs et de ceux qui veulent un PC complet de voyage plutôt qu'une simple tablette tactile.

Il y a cependant une chose a retenir dans ses deux versions, mais pour comprendre cette différence il faut d'abord regarder leurs spécifications techniques :

Version "Windows RT" :

Processeur : ARM nVidia (Tegra 3?)
Capacité : 32 Go ou 64 Go
Ecran : 1366x768, Gorilla Glass 2 de 10,6'', CleatType HD
Epaisseur : 9,3 mm
Poids : 676 g
Connectique : microSD, USB 2, Micro HD Vidéo
Wifi : MIMO
Batterie : 31.5 W-h 
Webcam : une devant et une derrière 

Prix supposé : 600$

Version "Windows 8 Pro" :

Processeur : Core i5 Ivy Bridge
Capacité : 64 Go ou 128 Go
Ecran : 1920x1080, Gorilla Glass 2 de 10,6'', CleatType HD
Epaisseur : 13,5 mm
Poids : 903 g
Connectique : microSDXC, USB 3, Mini Display Port Vidéo
Wifi : 2x2 MIMO
Batterie : 42 W-h
Webcam : une devant et une derrière   

Prix supposé : 1000$

Comme vous le voyez dans les spécifications, le processeur n'est pas tout a fait le même, ce que veut dire que sur la version Windows RT, vous ne pourrez pas installer vos applications Windows classique, cela résume à ne pouvoir utiliser que le Marketplace, c'est une utilisation identique a l'iPad d'Apple ou des tablettes sous Androïd. Cette version sera donc le concurrent direct de l'iPad !

La version Windows 8 Pro elle sera en avec une architecture x86 classique, ce qui veut dire que l'on peut installer un Visual Studio ou un Office (ou tout autre logiciel Windows classique) sans soucis, cette version sera donc plus pour les développeurs ou les personnes qui désirent un PC portatif tactile.

Accessoire tactile

Ce qui est aussi intéressant avec cette "Surface", c'est qu'elle possède une "Touch Cover" un peu comme l'iPad, mais celle-ci contient un clavier tactile et un touchpad ! Il va y en avoir 2 sortes, un mince qu'il suffira d'effleurer pour activer les touches et la souris, une autre plus classique avec une sensation de bouton pressé et donc plus épaisse.

Ce qui est intéressant aussi, c'est le pied rétractable à l'arrière de la tablette qui permet de la mettre à la vertical pour en faire un écran pour regarder des films ou coder.

Que devient l'ancienne marque Surface ?

L'ancienne "Surface 2" produite par Samsung (ou SUR40 pour les intimes), devient : "Samsung SUR40 avec Microsoft PixelSense". Tous les sites et blogs ont été refait pour ne plus faire apparaitre le terme "Surface". A ce porpos, pour accéder aux anciens sites Surface, voici les nouvelles URLs :

Site Microsoft PixelSense pour Samsung SUR40 (Anciennement Surface 2)

Blog Microsoft PixelSense (Anciennement Surface 2)

Je tiens a faire remarquer que le Black Blog est déjà à la page, les catégories et mots-clés ont été déjà modifiés pour accueillir la nouvelle nomenclature.

En ce qui concerne les MVPs Surface comme votre serviteur, je ne sais pas encore ce que cela va devenir, est-ce que nous pourrons exercer notre expérience sur les usages Tactiles et NUI sous le même nom et ainsi intégrer cette tablette dans notre scope ? Ou alors devenir les MVPs PixelSense ... Là dessus, seul l'avenir nous le dira.

Kinect SDK : Découverte

by Nicolas Calvi 3. avril 2012 14:21

Enfin ! C’est le 1 février dernier que Microsoft met à disposition du public la première version RTW du Kinect SDK for Windows. Au menu, optimisation, documentation et refonte des APIs. Cet article fait une comparaison avec la version BETA du SDK Kinect for Windows mais revient sur les principales fonctionnalités. Cet article fait suite à mon article paru dans le Programmez! 148 de Janvier 2012. Il est question de se familiariser avec le SDK.

1. Améliorations de l’architecture Kinect

Kinect est un véritable petit bijou de technologie. Outre les fonctionnalités disponibles sur Kinect pour XBOX 360, Kinect for Windows dispose de plusieurs améliorations :

- Existence d’un mode « near » qui permet de détecter des objets à partir de 40 cm de l’appareil.
- Possibilité de brancher jusqu’à 4 Kinect for Windows sur un même PC.
- Amélioration de la détection des squelettes.
- Intégration dans le SDK de la dernière version de Microsoft Speech Platform afin d’utiliser la reconnaissance vocale.

Pour pouvoir profiter des dernières améliorations, il va falloir acquérir un nouveau matériel estampiller « Kinect for Windows ». Ce nouveau Kinect, qui peut être acheté sur le Microsoft Store au prix de 249 euros, est une version amélioré de la « Kinect for Xbox » et permet l’utilisation du fameux mode « near », chose impossible avec une « Kinect for Xbox ».

2. Mode de licence

La plus grande interrogation à ce jour, est le mode de licence de Kinect. Jusqu’à maintenant, toute application créer avec le SDK Beta de Kinect n’était pas destinée à être vendu ou utilisé en entreprise, seul les étudiants, chercheurs et quidam du développement pouvaient s’amuser avec à des buts de prospection d’usage et aussi pour le fun.

Maintenant, il est possible de développer des applications à usage commerciale, mais il y a des conditions à respecter. Ce qu’il faut déjà comprendre, c’est que Microsoft se rémunère sur la vente de « Kinect for Windows », il faudra donc, pour déployer une application en entreprise, posséder un « Kinect for Windows » et non un « Kinect for Xbox ».

Dans les fait, le Kinect SDK permet de développer avec les deux matériels, mais une fois l’application exécutée sur la version « runtime » de Kinect, celui-ci va vérifier si le Kinect connecté est bien un « Kinect for Windows », si ce n’est pas le cas il va refuser de le prendre en charge.

Pour résumer, en développement (par le SDK) toutes les versions de Kinect sont acceptées, en mode runtime seuls les « Kinect for Windows » sont acceptés. D’ailleurs, on peut interpréter cela en se disant que l’utilisation d’un SDK non Microsoft pour utiliser Kinect est autorisé sous réserve que ce soit un matériel « Kinect for Windows » qui soit connecté. Bien sûr, prenez soin de vérifier cela auprès de Microsoft.

3. Utilisation du SDK

Au niveau du SDK, pas de changements de fond dans l’environnement de développement (Windows 7), l’outil de développement (Visual Studio 2010 toute version) et les langages de programmation disponibles (C# et C++) en 32 et 64 bits. C’est plutôt dans la forme que cela change.

Récupérer les Kinect connectés :

Dorénavant l’assembly utilisée pour développer sur Kinect est « Microsoft.Kinect ».

Afin de récupérer les informations relatives aux instances des Kinect connectés à la machine, on utilise maintenant une classe statique nommée simplement « KinectSensor ». Cette classe possède une propriété statique nommée « KinectSensors » permettant de récupérer la collection des Kinect connectés. Il suffit ensuite d’extraire de cette collection le ou les Kinect qui nous intéresse.

using Microsoft.Kinect;

private KinectSensor _kinectSensor;

public MaFenetre()
{
    // Si on trouve un kinect on l'initialise
    if (KinectSensor.KinectSensors.Count > 0)
    {
        this._kinectSensor = KinectSensor.KinectSensors[0];  
        this.InitializeKinect();
    }
}

Afin d’initialiser un Kinect il faut passer par plusieurs étapes. La première est de lancer la méthode Start de l’instance Kinect. On passe ensuite des paramètres pour éliminer le bruit (seulement nécessaire si on fait de la reconnaissance de squelette). On ouvre ensuite les flux qui nous intéressent (à savoir l’image VGA, l’image de profondeur et les squelettes) et on s’abonne à chaque événement de flux (ColorFrameReady, DepthFrameReady et SkeletonFrameReady) pour récupérer l’information.

Une autre alternative est de récupérer les informations de chaque événement en une fois avec l’événement « AllFramesReady » (figure 2). Ce dernier est une nouveauté par rapport aux anciennes versions du SDK qui nous obligeaient à nous abonner à chaque évènement séparément (ce qui est toujours possible en fonction des besoins). Mais parfois on a besoin d’avoir en même temps l’image vidéo et de profondeur, donc au lieu de la stocker pour l’utiliser plus tard, le runtime Kinect nous synchronise tous les éléments et nous les envois ensemble. Outre le fait que cela soit plus pratique, cela permet aussi un gain de traitement.

Il faut juste savoir que l’appel à la fonction « Enable() » est toujours nécessaire pour que les informations soient renseignées dans le « AllFramesReady », cette méthode démarre la capture du flux concerné.

private void InitializeKinect()
{
    // On démarre la scrutation
    this._kinectSensor.Start();

    // SmoothParamater pour éliminer le bruit
    TransformSmoothParameters parameters = new TransformSmoothParameters
    {
        Correction = 1.0f,
        JitterRadius = 0.01f,
        MaxDeviationRadius = 0.01f,
        Prediction = 1.0f,
        Smoothing = 0.9f
    };

    // Ouverture des flux
 this._kinectSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
 this._kinectSensor.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);
    this._kinectSensor.SkeletonStream.Enable(parameters);

    // On se branche sur tous les callbacks (ne pas se brancher sur les autres 
    // si on se branche sur celui-là
    this._kinectSensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(this.AllFramesReady);
}

Récupérer les données vidéo et les squelettes :

Afin de récupérer les données vidéo (image VGA et image de profondeur) on utilise l’argument de l’évènement levé quand toutes les frames (VGA, profondeur et squelette) sont disponibles. Les informations contenues dans l’argument vont nous être utiles pour construire notre image de rendu.

Pour obtenir les données de l’image VGA on utilise la méthode « OpenColorImageFrame », cette méthode va rendre disponible les informations coté managé et qui contient (quand l’image n’est pas nulle) un tableau de byte. Il suffit ensuite de copier ce flux dans notre application par la méthode « CopyPixelDataTo », dans notre exemple on copie les informations dans une variable que l’on nomme ici « pixelData ».

On utilise ensuite certaines propriétés de l’image (à savoir sa hauteur, sa longueur et le fameux « pixelData ») pour créer l’image VGA dans un type connu (WriteableBitmap dans notre exemple) et utilisable comme bon nous semble.

// Sert pour mettre à jour l’image
private readonly int _Bgr32BytesPerPixel = (PixelFormats.Bgr32.BitsPerPixel + 7) / 8;

private void AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
    // Gestion de l'image
    using (ColorImageFrame image = e.OpenColorImageFrame())
    {
        if (image != null)
        {
            byte[] pixelData = new byte[image.PixelDataLength];
            image.CopyPixelDataTo(pixelData);
            WriteableBitmap colorFrame = new WriteableBitmap(this._kinectSensor.ColorStream.FrameWidth, this._kinectSensor.ColorStream.FrameHeight, 96, 96, PixelFormats.Bgr32, null);
            colorFrame.WritePixels(new Int32Rect(0, 0, image.Width, image.Height), pixelData, image.Width * this._Bgr32BytesPerPixel, 0);
        }
    }
    // …
}

L’accès aux informations de l’image de profondeur de Kinect est relativement similaire à celui de l’image VGA. En effet, on utilise la méthode « OpenDepthImageFrame » de l’argument de l’évènement, on crée un tableau de type « short » correspondant au « pixelData » de l’image et on construit l’image de profondeur dans un WriteableBitmap.

Il y a néanmoins une petite subtilité qui est qu’il faut transformer un peu l’image pour l’exploiter. La conversion est expliquée dans le précédent article sur Kinect, les seuls changements sont l’apparition de masques pour faciliter le traitement. 

using (DepthImageFrame image = e.OpenDepthImageFrame())
{    
    if (image != null)
    {
        short[] depthImage = new short[image.PixelDataLength];
        image.CopyPixelDataTo(depthImage);

        // Récupération des informations de profondeur
        byte[] computeImage = this.ConvertDepthFrame(depthImage, image.Width, image.Height);

        // Conversion en image exploitable
        this.DepthFrame.WritePixels(new Int32Rect(0, 0, image.Width, image.Height), computeImage, image.Width *  _Bgr32BytesPerPixel, 0);
        // …
    }
}

private byte[] ConvertDepthFrame(short[] depthFrame, int imageWidth, int imageHeight)
{
    byte[] depthFrame32 = new byte[imageWidth * imageHeight * MainViewModel.Bgr32BytesPerPixel];

    for (int i16 = 0, i32 = 0; i16 < depthFrame.Length && i32 < depthFrame32.Length; i16++, i32 += 4)
    {
        // On récupère l'index joueur et la distance
        int player = depthFrame[i16] & DepthImageFrame.PlayerIndexBitmask;
        float realDepth = Convert.ToSingle(depthFrame[i16] >> DepthImageFrame.PlayerIndexBitmaskWidth);

        // Coder ici la convention de l’image …
    }

    // On retourne la frame
    return (depthFrame32);
}

Le processus pour récupérer les squelettes est similaire dans son principe. On utilise cette fois-ci la méthode  « OpenSkeletonFrame » de l’argument qui nous permet d’en extraire les informations des différents squelettes via la méthode « CopySkeletonDataTo ».

Une fois les squelettes récupérés il suffit de les trier pour obtenir ceux qui sont dans l’état « Tracked » c’est-à-dire quand Kinect arrive à définir le squelette et de faire des opérations sur ces derniers (comme récupérer les différents points du squelette et regarder leurs coordonnées).

// Recherche des squelettes
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
    if (frame != null && frame.SkeletonArrayLength > 0)
    {
        Skeleton[] skeletons = new Skeleton[frame.SkeletonArrayLength];
        frame.CopySkeletonDataTo(skeletons);

        var result = from p in skeletons
                         where p.TrackingState == SkeletonTrackingState.Tracked
                         select p;

        // Affichage des squelettes
        foreach (Skeleton item in result)
        {
            // Faire les opérations sur les différents squelettes
            // par exemple collecter tous les « Joints » et les afficher
        }
    }
}

En ce qui concerne les changements mineurs, on notera principalement la disparition d’indice de qualité W des SkeletonPoint.

Ainsi, nous avons pu voir les différents changements dus à la sortie officielle du SDK Kinect par rapport aux SDK antérieurs. Une multitude de possibilités s’offre au développeur une fois que les informations captées par Kinect sont transmises à la machine. Laissez parler votre imagination, une nouvelle ère est née !

Je vous laisse aussi télécharger la démo de cet article : KinectDemo.rar (147,64 kb) 

Merci à Patrick-André Marendat pour m'avoir aidé à rédiger cet article :)