// Para compilarlo, se debe correr el comando:
// $R CMD SHLIB steganography.c
#include <R.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
void bits(int *sound, int *nsound, unsigned short *bits, int *porcentaje, short *accion)
{
// sound: samples
// nsound: cantidad de las muestras
// bits: bits a utilizar de cada muestra
// porcentaje de muestras a modificar
// accion: 0riza (0), 1riza(1) o random(2)
// devuelve en el mismo sound
 
  short buildMask(short unsigned);
  unsigned short operar(unsigned short, short, short);
  int i, cambiar,cambios;
  float k,salto;
  short mask,umask;
  cambiar=(int)((*nsound)*(*porcentaje)/100);
  mask=buildMask(*bits);
  umask=(-1)^mask;
  srand ( time(NULL) );

//  Rprintf("total: %i\ncambiar: %i\n",*nsound,cambiar);
//  Rprintf("mask: %hd\n",mask);
//  Rprintf("umask: %hd\n",umask);

  switch (cambiar){
  case 0:
     break;
/*  case 1:
     i=(int)(*nsound)/2;
     switch (*accion){
     case 0: sound[i]=sound[i]&mask; break;
     case 1: sound[i]=sound[i]|umask; break;
     }
     break;*/
  default:
     salto=(float)(*nsound-1)/(cambiar-1);
//     Rprintf("salto: %f\n",salto);
     k=0;
     for(i=0; i < *nsound/2; i++) {
        if (i==(int)k ) {
           if (sound[2*i] >= 0) sound[2*i] =(int)(operar((short)sound[2*i],mask,*accion));
	   else sound[2*i] =(int)(operar(abs((short)sound[2*i]),mask,*accion))*-1;
           if (sound[2*i+1] >= 0) sound[2*i+1] =(int)(operar((short)sound[2*i+1],mask,*accion));
	   else sound[2*i+1] =(int)(operar(abs((short)sound[2*i+1]),mask,*accion))*-1;
	   cambios++;
	   cambios++;
	   k+=salto;
        }
     }
     break;
  }

Rprintf("Resumen:\n %i muestras cambiadas (%hd\%)\n %i bytes de ",cambios,(short)(((float)cambios/(*nsound))*100),(cambios*(*bits))/8);

switch (*accion){
case 0: Rprintf("ceros\n");
        break;
case 1: Rprintf("unos\n");
        break;
default: Rprintf("random\n");
        break;
}

}

unsigned short operar(unsigned short value, short mask, short accion){
     short umask;
     short azar;
     umask=(-1)^mask;
     switch (accion){
     case 0: return (value&mask); 
        break;
     case 1: return (abs(value|umask)); 
        break;
     default: 
        azar=(short)(rand()%32767);
//        return(((short)rand())&umask|((value)&mask));
        return((azar&umask)|(value&mask));
        break;
     }
}

short buildMask(unsigned short value){
   unsigned short c;
   unsigned short ret=0;
   ret--;
   for (c = 1; c <= value; c++){
      ret=ret << 1;
   }
   return(ret);
}

