Entrelacement et désentrelacement de flux organisés en 16bits (ex: PCM 16bits)

Contenu du snippet

.section .data
 
 .align 16;                            // on aligne les buffers sur 128bits (load/store SSE alignés)
 buffer_mono1:    .space 256*1024*2;    // buffer de 256K échantillons en 16bits signés mono(PCM classique)
 .align 16;                            // on aligne les buffers sur 128bits (load/store SSE alignés)
 buffer_mono2:    .space 256*1024*2;    // buffer de 256K échantillons en 16bits signés mono(PCM classique)
 .align 16;                            // on aligne les buffers sur 128bits (load/store SSE alignés)
 buffer_stereo:    .space 256*1024*2*2;  // buffer de 256K échantillons en 16bits signés stéréo entrelacé (PCM classique)
 
 nb_echantillons: .long 256*1024;      // nombre d'échantillons (attention: 1 échantillon = 2 octets !)
                                       // attention aussi a avoir un multiple de 8 echantillons !!
 
 .section .text
 
 ;// PARTIE ENTRELACEMENT
 entrelace:
      mov       $buffer_mono1,%eax;      // on charge le pointeur du 1er buffer mono dans EAX
      mov       $buffer_mono2,%ebx;      // on charge le pointeur du 2ème buffer mono dans EBX
      mov       $buffer_stereo,%edx;     // on charge le pointeur du buffer stéréo dans EDX
      mov       nb_echantillons,%ecx;    // on charge le contenu de nb_echantillons dans ECX
      sar       $3,%ecx;                 // on divise le nombre d'echantillons par 8
                                         // car on les traite 8 par 8
 boucle1:
      movdqa    (%eax),%xmm0;            // XMM0.W = [Md0 Md1 Md2 Md3 Md4 Md5 Md6 Md7] (Mono Droite) 
      movdqa    (%ebx),%xmm1;            // XMM1.W = [Mg0 Mg1 Mg2 Mg3 Mg4 Mg5 Mg6 Mg7] (Mono Gauche)
      pshufd    $0xE4,%xmm0,%xmm2;       // Recopie XMM0 dans XMM2 sans passer par l'unité de chargement SSE
      punpcklwd %xmm1,%xmm2;             // XMM2.W = [Md0 Mg0 Md1 Mg1 Md2 Mg2 Md3 Mg3]
      movdqa    %xmm2,(%edx);            // on écrit la première partie d'entrelacement
      punpckhwd %xmm1,%xmm0;             // XMM0.W = [Md4 Mg4 Md5 Mg5 Md6 Mg6 Md7 Mg7]
      movdqa    %xmm0,16(%edx);          // on écrit la deuxième partie d'entrelacement 16 octets plus loin
      add       $16,%eax;                // on se decale de 8 echantillons (16 octets) pour mono1
      add       $16,%ebx;                // on se decale de 8 echantillons (16 octets) pour mono2
      add       $32,%edx;                // on se decale de 8 echantillons (32 octets) pour stéréo
      dec       %ecx;                    // on decremente le nombre de paquet de 8 echantillons a traiter
      jnz       boucle1;                 // si ce n'est pas null, on continue a traiter
 fin_entrelace:                          // c'est fini ... on peut faire ce qu'on veut ensuite
 
 
 ;// PARTIE DESENTRELACEMENT
 desentrelace:
      mov       $buffer_mono1,%eax;      // on charge le pointeur du 1er buffer mono dans EAX
      mov       $buffer_mono2,%ebx;      // on charge le pointeur du 2ème buffer mono dans EBX
      mov       $buffer_stereo,%edx;     // on charge le pointeur du buffer stéréo dans EDX
      mov       nb_echantillons,%ecx;    // on charge le contenu de nb_echantillons dans ECX
      sar       $3,%ecx;                 // on divise le nombre d'echantillons par 8
                                         // car on les traite 8 par 8
 boucle2:
      movdqa    (%edx),%xmm0;            // XMM0.W = [Md0 Mg0 Md1 Mg1 Md2 Mg2 Md3 Mg3]
      movdqa    16(%edx),%xmm1;          // XMM1.W = [Md4 Mg4 Md5 Mg5 Md6 Mg6 Md7 Mg7]
      pshufd    $0xE4,%xmm0,%xmm2;       // Recopie XMM0 dans XMM2 sans passer par l'unite de chargement SSE
      pslld     $16,%xmm2;               // XMM2.W = [Mg0 0 Mg1 0 Mg2 0 Mg3 0]
      psrad     $16,%xmm2;               // XMM2.W = [0 Mg0 0 Mg1 0 Mg2 0 Mg3]
      movdqa    %xmm1,%xmm3;             // Recopie XMM1 dans XMM3
      pslld     $16,%xmm3;               // XMM3.W = [Mg4 0 Mg5 0 Mg6 0 Mg7 0]
      psrad     $16,%xmm3;               // XMM3.W = [0 Mg4 0 Mg5 0 Mg6 0 Mg7]
      packssdw  %xmm3,%xmm2;             // on packetise de double (32bits) vers word (16bits)
                                         // XMM2.W = [Mg0 Mg1 Mg2 Mg3 Mg4 Mg5 Mg6 Mg7]
      movdqa    %xmm2,(%eax);            // on stocke le resultat dans le 1er buffer mono
      psrad     $16,%xmm0;               // XMM0.W = [0 Md0 0 Md1 0 Md2 0 Md3]
      psrad     $16,%xmm1;               // XMM1.W = [0 Md4 0 Md5 0 Md6 0 Md7]
      packssdw  %xmm1,%xmm0;             // on packetise de double (32bits) vers word (16bits)
                                         // XMM0.W = [Md0 Md1 Md2 Md3 Md4 Md5 Md6 Md7]
      movdqa    %xmm0,(%ebx);            // on stocke le resultat dans le 2eme flux mono
      add       $16,%eax;                // on se deplace vers les 8 echantillons suivants (16 octets)
      add       $16,%ebx;                // on se deplace vers les 8 echantillons suivants (16 octets)
      add       $32,%edx;                // on se deplace vers les 8 echantillons suivants (32 octets)
      dec       %ecx;                    // on decremente le nombre de paquet de 8 echantillons a traiter
      jnz       boucle1;                 // si ce n'est pas null, on continue a traiter
 fin_desentrelace:                       // c'est fini ... on peut faire ce qu'on veut ensuite
 


Compatibilité : Assembleur x86

Disponible dans d'autres langages :

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.