Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

CONCATENATION DE FICHIERS WAV


Information sur la source

Catégorie :Fichier / Disque Niveau : Débutant Date de création : 25/05/2003 Date de mise à jour : 25/05/2003 17:00:09 Vu / téléchargé: 8 895 / 398

Note :
9 / 10 - par 2 personnes
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (13)
Ajouter un commentaire et/ou une note


Description

Une unité offrant une fonction "Concatener", qui permet d'assembler en un seul fichier WAV plusieurs fichiers WAV donnés... J'ai fait ça pour une personne qui me l'a demandé, mais je pense que ça peut servir à d'autres !!

Dans le ZIP, y a une petite "démo" pour voir comment utiliser la fonction... Vous verrez, c'est on ne peut plus simple !!

MISE A JOUR :
Après le comentaire de bgK, fallait bien que je modifie un peu mon source :
Les fichiers qui ne sont pas des fichiers WAVE PCM sont ignorés, ainsi que ceux qui n'ont pas le même format audio que le premier fichier enregistré
 

Source

  • Voici le nouveau contenu de l'unité uConcatWAV :
  • unit uConcatWAV;
  • interface
  • uses SysUtils, Classes, Dialogs;
  • //Déclaration des différents headers contenus dans un fichier WAV...
  • //Allez faire une recherche sur www.wotsit.org pour des informations précises
  • //sur le format WAV ! (ou sur google : "WAVE File Format specification" !)
  • type
  • THeaderRIFF = Packed Record
  • ID : Array[1..4]Of Char;
  • Taille: Cardinal;
  • Format: Array[1..4]Of Char;
  • end;
  • THeaderFormat = Packed Record
  • ID : Array[1..4]Of Char;
  • Taille: Cardinal;
  • Format: WORD;
  • Mode : WORD;
  • SRate : Cardinal; //=Sample Rate
  • BRate : Cardinal; //=Byte Rate
  • Align : WORD;
  • BPS : WORD; //Bits Per Sample
  • //FACULTATIF (INEXISTANT POUR LE FORMAT PCM)\\
  • //TailleExtra: WORD;\\
  • //Extras: Array Of Byte;\\
  • end;
  • THeaderData = Packed Record
  • ID : Array[1..4]Of Char;
  • Taille: Cardinal;
  • //Inutile ici Datas: Array Of Byte;
  • end;
  • TWAVE = Packed Record //Ajouté pour avoir un format de référence servant
  • RIFF: THeaderRIFF; //à ignorer les fichiers dont le format diffère
  • Fmt : THeaderFormat;
  • Data: THeaderData;
  • end;
  • function Concatener(Liste: PAnsiChar; Sortie: String): String;
  • implementation
  • function WAV_Valid(Fichier: String): Boolean;
  • var WAV: TFileStream;
  • RIFF: Array[1..4]Of Char;
  • WAVEfmt: Array[1..8]Of Char;
  • PCM: WORD;
  • begin
  • Result := False;
  • Try
  • WAV := TFileStream.Create(Fichier, fmOpenRead);
  • WAV.Read(RIFF, 4);
  • If RIFF <> 'RIFF' then Exit;
  • WAV.Seek(8, soFromBeginning);
  • WAV.Read(WAVEfmt, 8); //Lecture de "WAVE" et "fmt " en même temps
  • If WAVEfmt <> 'WAVEfmt ' then
  • begin
  • WAV.Free;
  • Exit;
  • end;
  • WAV.Seek(20, soFromBeginning);
  • WAV.Read(PCM, 2);
  • If PCM <> 1 then
  • begin
  • WAV.Free;
  • Exit;
  • end;
  • except
  • On Exception do Exit;
  • end;
  • WAV.Free;
  • Result := True;
  • end;
  • function FormatOK(Ref, Fich: TWAVE): Boolean;
  • begin
  • Result := (Ref.Fmt.Format = Fich.Fmt.Format) and (Ref.Fmt.Mode = Fich.Fmt.Mode ) and
  • (Ref.Fmt.SRate = Fich.Fmt.SRate ) and (Ref.Fmt.BRate = Fich.Fmt.BRate) and
  • (Ref.Fmt.Align = Fich.Fmt.Align ) and (Ref.Fmt.BPS = Fich.Fmt.BPS );
  • end;
  • function Concatener(Liste: PAnsiChar; Sortie: String): String;
  • var Lst: TStringList;
  • Source, Dest: TFileStream;
  • Temp: TMemoryStream;
  • i: Integer;
  • Fichier, Ref: TWAVE;
  • begin
  • Result := Sortie;
  • Try
  • Try
  • Lst := TStringList.Create;
  • Lst.SetText(Liste);
  • Temp := TMemoryStream.Create;
  • Dest := TFileStream.Create(Sortie, fmCreate);
  • for i := 0 to Lst.Count - 1 do
  • If WAV_Valid(Lst[i]) then
  • begin
  • Try
  • Source := TFileStream.Create(Lst[i], fmOpenRead);
  • Source.Read(Fichier.RIFF, SizeOf(THeaderRIFF));
  • Source.Read(Fichier.Fmt, SizeOf(THeaderFormat));
  • Source.Read(Fichier.Data, SizeOf(THeaderData));
  • if i = 0 then
  • begin
  • Ref.RIFF := Fichier.RIFF;
  • Ref.Fmt := Fichier.Fmt;
  • Ref.Data := Fichier.Data;
  • end;
  • If FormatOK(Ref, Fichier) then
  • Temp.CopyFrom(Source, Fichier.Data.Taille);
  • finally
  • Source.Free;
  • end;
  • end;
  • Ref.RIFF.Taille := 36 + Temp.Size;
  • Ref.Data.Taille := Temp.Size;
  • Dest.Write(Ref.RIFF, SizeOf(Ref.RIFF));
  • Dest.Write(Ref.Fmt, SizeOf(Ref.Fmt));
  • Dest.Write(Ref.Data, SizeOf(Ref.Data));
  • Dest.CopyFrom(Temp, 0);
  • except
  • On Exception Do
  • begin
  • Result := 'Erreur';
  • Exit;
  • end;
  • end;
  • finally
  • Lst.Free;
  • temp.Free;
  • Dest.Free;
  • end;
  • end;
  • end.
Voici le nouveau contenu de l'unité uConcatWAV :
unit uConcatWAV;

interface
uses SysUtils, Classes, Dialogs;

//Déclaration des différents headers contenus dans un fichier WAV...
//Allez faire une recherche sur www.wotsit.org pour des informations précises
//sur le format WAV ! (ou sur google : "WAVE File Format specification" !)
type
  THeaderRIFF = Packed Record
    ID    : Array[1..4]Of Char;
    Taille: Cardinal;
    Format: Array[1..4]Of Char;
  end;

  THeaderFormat = Packed Record
    ID    : Array[1..4]Of Char;
    Taille: Cardinal;
    Format: WORD;
    Mode  : WORD;
    SRate : Cardinal; //=Sample Rate
    BRate : Cardinal; //=Byte Rate
    Align : WORD;
    BPS   : WORD;     //Bits Per Sample
  //FACULTATIF (INEXISTANT POUR LE FORMAT PCM)\\
  //TailleExtra: WORD;\\
  //Extras: Array Of Byte;\\
  end;

  THeaderData = Packed Record
    ID    : Array[1..4]Of Char;
    Taille: Cardinal;
//Inutile ici Datas: Array Of Byte;
  end;

  TWAVE = Packed Record //Ajouté pour avoir un format de référence servant
    RIFF: THeaderRIFF;  //à ignorer les fichiers dont le format diffère
    Fmt : THeaderFormat;
    Data: THeaderData;
  end;

function Concatener(Liste: PAnsiChar; Sortie: String): String;

implementation

function WAV_Valid(Fichier: String): Boolean;
var WAV: TFileStream;
    RIFF: Array[1..4]Of Char;
    WAVEfmt: Array[1..8]Of Char;
    PCM: WORD;
begin

  Result := False;

  Try
    WAV := TFileStream.Create(Fichier, fmOpenRead);

    WAV.Read(RIFF, 4);
    If RIFF <> 'RIFF' then Exit;

    WAV.Seek(8, soFromBeginning);
    WAV.Read(WAVEfmt, 8); //Lecture de "WAVE" et "fmt " en même temps
    If WAVEfmt <> 'WAVEfmt ' then
      begin
        WAV.Free;
        Exit;
      end;

    WAV.Seek(20, soFromBeginning);
    WAV.Read(PCM, 2);
    If PCM <> 1 then
      begin
        WAV.Free;
        Exit;
      end;

  except
    On Exception do Exit;
  end;

  WAV.Free;

  Result := True;

end;

function FormatOK(Ref, Fich: TWAVE): Boolean;
begin

  Result := (Ref.Fmt.Format = Fich.Fmt.Format) and (Ref.Fmt.Mode  = Fich.Fmt.Mode ) and
            (Ref.Fmt.SRate  = Fich.Fmt.SRate ) and (Ref.Fmt.BRate = Fich.Fmt.BRate) and
            (Ref.Fmt.Align  = Fich.Fmt.Align ) and (Ref.Fmt.BPS   = Fich.Fmt.BPS  );

end;

function Concatener(Liste: PAnsiChar; Sortie: String): String;
var Lst: TStringList;
    Source, Dest: TFileStream;
    Temp: TMemoryStream;
    i: Integer;
    Fichier, Ref: TWAVE;
begin

  Result := Sortie;

  Try
    Try
      Lst := TStringList.Create;
      Lst.SetText(Liste);

      Temp := TMemoryStream.Create;
      Dest := TFileStream.Create(Sortie, fmCreate);

      for i := 0 to Lst.Count - 1 do
       If WAV_Valid(Lst[i]) then
        begin
          Try
            Source := TFileStream.Create(Lst[i], fmOpenRead);

            Source.Read(Fichier.RIFF, SizeOf(THeaderRIFF));
            Source.Read(Fichier.Fmt, SizeOf(THeaderFormat));
            Source.Read(Fichier.Data, SizeOf(THeaderData));

            if i = 0 then
              begin
                Ref.RIFF := Fichier.RIFF;
                Ref.Fmt  := Fichier.Fmt;
                Ref.Data := Fichier.Data;
              end;

            If FormatOK(Ref, Fichier) then
              Temp.CopyFrom(Source, Fichier.Data.Taille);

          finally
            Source.Free;
          end;
        end;

      Ref.RIFF.Taille := 36 + Temp.Size;
      Ref.Data.Taille := Temp.Size;

      Dest.Write(Ref.RIFF, SizeOf(Ref.RIFF));
      Dest.Write(Ref.Fmt, SizeOf(Ref.Fmt));
      Dest.Write(Ref.Data, SizeOf(Ref.Data));
      Dest.CopyFrom(Temp, 0);

    except
      On Exception Do
        begin
          Result := 'Erreur';
          Exit;
        end;
    end;
  finally
    Lst.Free;
    temp.Free;
    Dest.Free;
  end;

end;

end.

Conclusion

Je crois que c'est tout, à part une petite limitation :
sachant que je ne sais pas faire de "resampling", il faut que tous les fichiers choisis soient au même format audio (par exemple : PCM, 22050Hz, Stéréo, 16 bits par sample) pour que le fichier de sortie soit correct !

Bonne prog' à tous !
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Commentaires et avis

signaler à un administrateur
Commentaire de Bestiol le 25/05/2003 00:45:17

Petite précision pour la ligne "RIFF.Taille := 36 + Temp.Size;" :
Le 36 correspond à la taille de tous les headers, qui est fixe pour le format PCM

signaler à un administrateur
Commentaire de bgK le 25/05/2003 09:02:18

C'est bien, et utile, mais j'ai juste deux petites remarques/questions :
- à priori, il suffit de renommer n'importe quel fichier en .wav pour pouvoir le concaténer avec un autre. Peut-être qu'une petite vérification au niveau de la signature de(s) l'en-tête(s) ne serait pas de trop.
- Sinon, dans ta fonction concaténer, pourquoi utiliser une variable de type PAnsiChar ?? Un TStrings ou TStringList n'aurait-il pas fait l'affaire ??

signaler à un administrateur
Commentaire de Bestiol le 25/05/2003 14:27:11

Salut bgK !!

Pour at première remarque, c'est erxct, je ne fais aucun vérification !! Pour être sûr à 100% qu'il s'agit bien d'un fichier WAVE PCM :
-A l'offset 0, 4 caratères : "RIFF"
-A l'offset 8, 4 caractères : "WAVE" suivis à l'offset 12 de "fmt "
-A l'offset 20, une variable de 2 octets (WORD) qui doit être égale à 1 pour le format PCM
Voilà pour la vérification !

Pour le PAnsiChar, j'ai fait ça car j'ai gardé en mémoire un problème que j'avais eu en utilisant un TStringList en paramètre d'une fonction... Je sais plus très bien ce qui s'était passé, mais là, j'ai pas cherché, j'ai mis directement PAnsiChar, vu qu'on peut facilement utiliser StringList.Lines.GetText et SetText !

Merci pour les commentaires, et bonne prog' !

signaler à un administrateur
Commentaire de bgK le 25/05/2003 19:24:03

Cool, bravo !!!

signaler à un administrateur
Commentaire de subzero le 28/05/2003 06:43:13

Salut!

J'ai commencé un tutoriel sur le format WAV et il y aura quelques sources intérressantes pour Delphi! Si vous avez des conseils, ou des remarques, des idées, etc.... Contactez-moi!

http://site.voila.fr/subut/tuto_wav.htm

&lt;subut2@hotmail.com&gt;

signaler à un administrateur
Commentaire de subzero le 28/05/2003 06:58:05

Au fait, la taille de l'header du fichier WAV est 44 octets, et non 36!
Bref, mon tutoriel sur le format WAV vous sera sûrement bénéfique (j'espère). Il ya des sources complètes pour convertir les formats! Par exemple convertir un sample 16 bits stéréo en 16 bits mono, ou en 8 bits stéréo... Pour la convertion de la fréquence d'échantillonnage, je suis en train de m'en occuper! à+

signaler à un administrateur
Commentaire de Bestiol le 28/05/2003 12:14:58

Pour la taille du header, je me suis référé à un document que j'ai trouvé sur le Net... Mais ça marche très bien avec 36 !! Je verrai ce qu eça fait avec 44...

signaler à un administrateur
Commentaire de subzero le 28/05/2003 12:24:28

Je suis sûr et certain que pour le format WAV (PCM), il faut 44 octets au header, sinon, ya un gros problème avec mes bouquins! lol
Autrement, je suis entrain de programmer un ripper de CD-Audio avec convertion du WAV en MP3! C'est intérressant en tous les cas, à+

signaler à un administrateur
Commentaire de Bestiol le 28/05/2003 18:41:50

Salut Sub0 !!

Pour le Header, j'ai vérifié, c'est bien 44 octets !! Ce qui est bizarre, c'est que ça marche également avec 36 dans mon programme !!

Bonne chance pour ton projet de prog' !

signaler à un administrateur
Commentaire de subzero le 28/05/2003 21:19:40

Merci! Ben, c'est bien parti là! J'ai déjà le ripper au point!
Il manque plus que le MP3 (encodage direct de l'extraction).
Toutes les sources seront dans mon tuto! C'est cadeau! à+

signaler à un administrateur
Commentaire de delphifan le 30/03/2004 11:07:57

tout d'abord merci pour les efforts que vous avez fait pour faire réussir ce programme ,ton idée ma beaucoup apprécier,elle est simple et au même temps avantageuse sauf que vous avez travaillez
que sur les formats pcm sans prendre en compte le cas
ou data ="fact" .
comme les autres commentaires ,bien que le header est sur 44 alors que ça marche sur 36,c'est ettonant n'est ce pas !j'ai essaie ce programme avec C++builder mais il m'a poser une exception de violation d'adresse au niveau de l'instruction :Temp-&gt;CopyFrom(Source, Fichier.Data.Taille);voulez vous bien m'aider pour résoudre ce problème réponder moi le plutot possible,et merci.

            

signaler à un administrateur
Commentaire de Bestiol le 18/08/2004 19:35:22

delphifan a eu la gentillesse de m'envoyer un message expliquant notre petite discussion sur la taille du header !! Voici son message qui explique le pourquoi du moment ! ;o)

"la valeur 36 est juste, et c'est pas etonnant, car si on regarde bien la définition de bloc RIff
on trouve  que ce dèrnier contient les informations suivantes:
- 4 octets pour les caractères ascii "riff".ensuite vient les 4octets qui détermine la longueur totale en octet de la suite de  du fichier  et non pas la taille total  du fichier
càd riff.taille= la taille total de fichier -8 octets(4octets pour les caractères "riff"+4octets pour la taille )
autrement dit,c'est la taille de fichier apartir de l'octet numéro 8jusqu'à la fin du ficchier d'ou 44-8=36.
donc riff.taille =36+taille de données est juste.rien ne vient de hasard."

Vala vala... Merci Delphifan ! =0)
Et bonne prog' à tous !
Bestiol.

signaler à un administrateur
Commentaire de subzero le 31/08/2004 06:12:13

Salut! Bestio: Si tu veux, tu peux ajouter des fonctionalités intérressantes à ton projet, comme convertir la fréquence ou le format d'un sample avant la fusion... Le savais-tu: Pour que les samples se fusionnent correctement, il faut qu'il est la même valeur d'amplitude à l'endroit de la fusion, sinon, on peut obtienir un craquement à l'écoute de cet position... Une solution est d'ajouter fade-out à la fin du sample et fade-in au début... Si tu es intérressé, contacte-moi! Autre chose, j'ai découvert une erreur dans mon tuto -(merci Steph!). Il sagit de la fonction de conversion 16bits non-signés -> signés. Voici la correction (il manquait le signe = dans la condition):

donnee:=donnee+32768;
IF(donnee>=65536)THEN donnee:=donnee-65536;

à+

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,624 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.