Concatenation de fichiers wav

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 / Exemple :


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 !

Codes Sources

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.