Logo Search packages:      
Sourcecode: xcfa version File versions

tags_wav.c

 /*
 * file    : tags_wav.c
 * project : xcfa
 * with    : Gtk-2
 *
 * xcfa - GTK+ implementation of the GNU shell command
 * GNU General Public License
 * 2003,2004,2005,2006,2007,2008,2009 Claude Bulin
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * OLD ADRESS:
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * NEW ADRESS:
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 */



#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include "support.h"

#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include "global.h"
#include "file.h"
#include "level.h"
#include "tags.h"


/*
*---------------------------------------------------------------------------
* DOCUMENATION ENTETE
*---------------------------------------------------------------------------
* http://col2000.free.fr/vocal/formawav.htm
* http://www.commentcamarche.net/audio/wav.php3
* http://pagesperso-orange.fr/vb-audio/fr/pub/tech_000/wave_format.htm
* http://www.techno-science.net/?onglet=glossaire&definition=11154
*---------------------------------------------------------------------------

L'entête mesure 56 octets, et s'étend donc de l'adresse 00h à l'adresse 38h.

Les fichiers WAV utilisent le format RIFF ; définition du format RIFF :

Octets 1 à 4   : Caractères 'RIFF' [52h 49h 46h 46h] identifiant le format.
Octets 5 à 8   : Longueur du groupe de données au format WAV =
                 [30h.00h.01h.00h] = 00010030h = 65584 octets,
                 (le reste du fichier, car 65584+8 = 65592 octets).
Octets 9 à 16  : Caractères 'WAVEfmt ' identifiant le format WAV.

Les octets 17 à 56 définissent les paramètres du format 'WAV' :

Octets 17 à 20 : [10.00.00.00] = 00000010h = 16 = nombre d'octets
                 utilisés après pour définir le format.
Octets 21 à 22 : [01.00] = 0001h = 1 = numéro de format du fichier
                 (pas de compression, format PCM classique).
Octets 23 à 24 : [01.00] = 0001h = 1 : nombre de canaux : ici, mono.
Octets 25 à 28 : [11.2B.00.00] = 00002B11h = 11025, fréquence
                 d'échantillonnage (en Hz), c'est à dire le nombre
                 d'échantillons pas seconde.
Octets 29 à 32 : [11.2B.00.00] = 00002B11h = 11025, nombres d'octets par
                 seconde, ce qui revient au même car un échantillon mesure
                 un octet et l'on est en mono.
Octets 33 à 34 : [01.00] = 0001h = 1 = Produit du nombre de canaux par le
                 nombre d'octets par échantillon (ici 1x1=1).
Octets 35 à 36 : [08.00] = 0008h = 8 bits par échantillon (valeurs
                 possibles : 8, 12 ou 16).
Octets 37 à 48 : [66.61.63.74][04.00.00.00][00.00.01.00] = 'fact', 4, 65536.
                 Champ sur lequel je n'ai pas de précision ; je pense
                 que 'fact' annonce des informations, que les 4 octets
                 suivants indiquent la taille de ces infos (4 octets),
                 et que dans ce cas, l'info est le nombre d'échantillons,
                 lequel est repris après par 'data', soit 65536.
Octets 49 à 52 : 'data' : annonce l'arrivée des données.
Octets 53 à 56 : [00.00.01.00] = 00010000h = 65536 : taille des données.

Les 65536 octets suivants : valeurs numériques successives des échantillons, oscillant autour
de la valeur moyenne 80h, selon l'amplitude et le signe du signal d'entrée...
*/



/*
*---------------------------------------------------------------------------
* VARIABLES
*---------------------------------------------------------------------------
*/

typedef struct {              /* entete fichier WAV */

      gchar          tag1[ 5 ];     /* ( 4 octets) : Constante "RIFF" */
      guint32        size1;         /* ( 4 octets) : Taille du fichier moins 8 octets */
      gchar          tag2 [ 15 ];   /* (14 octets) : Constante "WAVEfmt......." */
      guint16        mode;          /* ( 2 octets) : Mode (1 pour mono ou 2 pour stereo) */
      guint32        freq;          /* ( 4 octets) : Frequence d'échantillonage (en Hertz) */
      guint32        bytepersec;    /* ( 4 octets) : Nombre de bits par seconde de musique */
      guint16        nbrbyte;       /* ( 2 octets) : Nombre d'octets par échantillon */
      guint16        format;        /* ( 2 octets) : Nombre de bits par donnée */
      guint32        tag3;          /* ( 4 octets) : Constante "data" */
      guint32        size2;         /* ( 4 octets) : Taille du fichier moins 116 octets */

} HEADER_WAV;

/*
*---------------------------------------------------------------------------
* FILE IS WAV ?
*---------------------------------------------------------------------------
*/

gboolean tagswav_file_is_wav (gchar *namefile)
{
      FILE        *fp = NULL;
      HEADER_WAV   buf;
      
      if ((fp = fopen (namefile, "r")) == NULL) return (FALSE);
      fread(&buf.tag1, 1, 4, fp);
      buf.tag1 [ 4 ] = '\0';
      fread(&buf.tag2, 1, 4, fp);
      fread(&buf.tag2, 1, 14, fp);
      fclose (fp);
/*
g_print("buf.tag1 = %s\n", buf.tag1);
g_print("buf.tag2 = %s\n", buf.tag2);
*/    
      if ((buf.tag1 [ 0 ] == 'R' &&
           buf.tag1 [ 1 ] == 'I' &&
           buf.tag1 [ 2 ] == 'F' &&
           buf.tag1 [ 3 ] == 'F') &&
          
          (buf.tag2 [ 0 ] == 'W' &&
           buf.tag2 [ 1 ] == 'A' &&
           buf.tag2 [ 2 ] == 'V' &&
           buf.tag2 [ 3 ] == 'E')) return (TRUE);

      return (FALSE);
}

/*
*---------------------------------------------------------------------------
* GET HEADER
*---------------------------------------------------------------------------
*/

/*
void tagswav_print_info (HEADER_WAV *info)
{
      gchar str [ 20 ];
      gint i;

      g_print ("\n");
      for (i=0; i<4; i++) str [i] = info->tag1[i];
      str [ i ] = '\0';
      g_print ("tag1[ 4 ]    (4 octets) : Constante RIFF                        :%s\n", str);
      g_print ("tag1[ 4 ]    (4 octets) : Constante RIFF                        :%s\n", info->tag1);
      g_print ("size1        (4 octets) : Taille du fichier moins 8 octets      :%d\n", info->size1);
      for (i=0; i<14; i++) str [i] = info->tag2[i];
      str [ i ] = '\0';
      g_print ("tag2 [ 14 ]  (14 octets): Constante WAVEfmt.......              :%s\n", str);
      g_print ("mode         (2 octets) : Mode (1 pour mono ou 2 pour stereo)   :%d\n", info->mode);
      g_print ("freq         (4 octets) : Frequence d'échantillonage (en Hertz) :%d\n", info->freq);
      g_print ("bytepersec   (4 octets) : Nombre de bits par seconde de musique :%d\n", info->bytepersec);
      g_print ("nbrbyte      (2 octets) : Nombre d'octets par échantillon       :%d\n", info->nbrbyte);
      g_print ("format       (2 octets) : Nombre de bits par donnée             :%d\n", info->format);
      g_print ("tag3         (4 octets) : Constante data                        :%d\n", info->tag3);
      g_print ("size2        (4 octets) : Taille du fichier moins 116 octets    :%d\n", info->size2);
      g_print ("\n");
}
*/

INFO_WAV *tagswav_remove_info (INFO_WAV *info)
{
      if (info) {
            g_free (info->namefile);
            g_free (info->time);
            g_free (info->hertz);
            g_free (info->voie);
            g_free (info->bits);

            info->tags = (TAGS *)tags_remove (info->tags);

            g_free (info);
            info = NULL;
      }
      return ((INFO_WAV *)NULL);
}

/* Fonction reprise depuis: xmms-1.2.10+20070601
*/
gboolean read_le_long(FILE * file, guint32 *ret)
{
      guint32 l;
      if (fread(&l, sizeof (l), 1, file) != 1)
            return FALSE;
      *ret = GUINT32_FROM_LE(l);
      return TRUE;
}
/* Fonction reprise depuis: xmms-1.2.10+20070601
*/
gboolean read_le_short(FILE * file, guint16 *ret)
{
      guint16 s;
      if (fread(&s, sizeof (s), 1, file) != 1)
            return FALSE;
      *ret = GUINT16_FROM_LE(s);
      return TRUE;
}

gboolean tagswav_file_is_mono (gchar *namefile)
{
      FILE        *fp = NULL;
      HEADER_WAV   buf;
      
      if ((fp = fopen (namefile, "r")) == NULL) return (FALSE);

      /* Lecture entete WAV inspiree de: xmms-1.2.10+20070601
      */
      fread (&buf.tag1, 1, 4, fp);
      read_le_long (fp, &buf.size1);
      fread (&buf.tag2, 1, 14, fp);
      read_le_short (fp, &buf.mode);
      read_le_long (fp, &buf.freq);
      read_le_long (fp, &buf.bytepersec);
      read_le_short (fp, &buf.nbrbyte);
      read_le_short (fp, &buf.format);
      read_le_long (fp, &buf.tag3);
      read_le_long (fp, &buf.size2);
      
      fclose (fp);
/*
PRINTBOOL("buf.mode",((buf.mode == 1) ? TRUE : FALSE));
*/
      /*mode         (2 octets) : Mode (1 pour mono ou 2 pour stereo)*/
      return (buf.mode == 1 ? TRUE : FALSE);
}

gboolean tagswav_file_ChangeBitrate (gchar *namefile)
{
      FILE        *fp = NULL;
      HEADER_WAV   buf;
      
      if ((fp = fopen (namefile, "r")) == NULL) return (FALSE);

      /* Lecture entete WAV inspiree de: xmms-1.2.10+20070601
      */
      fread (&buf.tag1, 1, 4, fp);
      read_le_long (fp, &buf.size1);
      fread (&buf.tag2, 1, 14, fp);
      read_le_short (fp, &buf.mode);
      read_le_long (fp, &buf.freq);
      read_le_long (fp, &buf.bytepersec);
      read_le_short (fp, &buf.nbrbyte);
      read_le_short (fp, &buf.format);
      read_le_long (fp, &buf.tag3);
      read_le_long (fp, &buf.size2);
      
      fclose (fp);
      
      return ((buf.mode > 2 || buf.freq != 44100 || buf.format >= 32) ? TRUE : FALSE);
}
INFO_WAV *tagswav_get_info (DETAIL *detail, gchar *namefile)
{
      FILE        *fp = NULL;
      HEADER_WAV   buf;
      INFO_WAV    *ptrinfo = NULL;
      gint         m;
      gint         s;
      gint         sec;
      size_t       len;
      
      /*PRINT_FUNC_LF();*/
      ptrinfo = (INFO_WAV *)g_malloc0 (sizeof (INFO_WAV));
      if (!ptrinfo) {
            g_print ("!---------------------------------------\n");
            PRINT_FUNC_LF();
            g_print ("!---------------------------------------\n");
            g_print ("! PTRINFO EST NULL  :(\n");
            g_print ("!---------------------------------------\n");
            return (NULL);
      }

      if ((fp = fopen (namefile, "r")) == NULL) {
            g_free (ptrinfo);
            ptrinfo = NULL;
            return (NULL);
      }

      /* Lecture entete WAV inspiree de: xmms-1.2.10+20070601
      */
      fread (&buf.tag1, 1, 4, fp);
      read_le_long (fp, &buf.size1);
      fread (&buf.tag2, 1, 14, fp);
      read_le_short (fp, &buf.mode);
      read_le_long (fp, &buf.freq);
      read_le_long (fp, &buf.bytepersec);
      read_le_short (fp, &buf.nbrbyte);
      read_le_short (fp, &buf.format);
      read_le_long (fp, &buf.tag3);
      read_le_long (fp, &buf.size2);
      
      fclose (fp);
/*
buf.tag1 [ 5 ] = '\0';
g_print ("tag1[ 4 ]    (4 octets) : Constante RIFF                        :%s\n", buf.tag1);
g_print ("size1        (4 octets) : Taille du fichier moins 8 octets      :%d\n", buf.size1);
buf.tag2 [ 15 ] = '\0';
g_print ("tag2 [ 14 ]  (14 octets): Constante WAVEfmt.......              :%s\n", buf.tag2);
g_print ("mode         (2 octets) : Mode (1 pour mono ou 2 pour stereo)   :%d\n", buf.mode);
g_print ("freq         (4 octets) : Frequence d'échantillonage (en Hertz) :%d\n", buf.freq);
g_print ("bytepersec   (4 octets) : Nombre de bits par seconde de musique :%d\n", buf.bytepersec);
g_print ("nbrbyte      (2 octets) : Nombre d'octets par échantillon       :%d\n", buf.nbrbyte);
g_print ("format       (2 octets) : Nombre de bits par donnée             :%d\n", buf.format);
g_print ("tag3         (4 octets) : Constante data                        :%d\n", buf.tag3);
g_print ("size2        (4 octets) : Taille du fichier moins 116 octets    :%d\n", buf.size2);
g_print ("\n");
*/
      /* Modifications de l'entete IF BAD
      */
      len = infosong_get_size_file (namefile);
      buf.size2 = len - 116;
      if (buf.nbrbyte <= 1) buf.nbrbyte = 4;
      if (buf.format <= 0) buf.format = 16;
      
      /* RE-Ecriture de l'entete
      */
      /*
      if ((fp = fopen (namefile, "r+")) != NULL) {
            fwrite(buf, sizeof(HEADER_WAV), 1, fp);
            fclose (fp);
      }
*/
      if (buf.size2 == 0 || buf.bytepersec == 0) {
            g_free (ptrinfo);
            ptrinfo = NULL;
            return (NULL);
      }

      ptrinfo->namefile = g_strdup (namefile);

      /* calcul de la duree */
      sec = buf.size2 / buf.bytepersec;
      
      if (detail != NULL) {
            detail->ValuePlay.SecTime = sec;
      }
/*
g_print ("detail->ValuePlay.SecTime=%d\n",detail->ValuePlay.SecTime);
*/
      ptrinfo->SecTime = sec;
      ptrinfo->ValueMark.SecTime    = sec;
      ptrinfo->ValueMark.ValueMarkA = 0.0;
      ptrinfo->ValueMark.ValueMarkB = 100.0;
      ptrinfo->ValueMark.Value = 0.0;

      s = sec % 60; sec /= 60;
      m = sec % 60; sec /= 60;
      if (sec > 0) ptrinfo->time = g_strdup_printf ("%02d:%02d:%02d", sec, m, s);
      else         ptrinfo->time = g_strdup_printf ("%02d:%02d", m, s);

      /* mode */
      ptrinfo->voie = g_strdup_printf ("%d", buf.mode);

      /* freq */
      ptrinfo->hertz = g_strdup_printf ("%d", buf.freq);

      /* format */
      ptrinfo->bits = g_strdup_printf ("%d", buf.format);

      ptrinfo->tags = (TAGS *)tags_alloc (FALSE);
      tags_set (namefile, ptrinfo->tags);
      
/*
ptrinfo->level = level_get_from (FILE_IS_WAV, namefile);
g_print ("%s\t%d\n", namefile, ptrinfo->level);
*/
      ptrinfo->LevelDbfs.level = -1;
      ptrinfo->LevelDbfs.NewLevel = -1;

      return (ptrinfo);
}






Generated by  Doxygen 1.6.0   Back to index