![]() |
|
|
#1
|
|||
|
|||
|
Здравствуйте, мне нужно слить два файла wav в один, я написал вот этот код:
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Panel1: TPanel;
Panel2: TPanel;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TWaveHeader = record
Marker1: Array[0..3] of Char;
BytesFollowing: LongInt;
Marker2: Array[0..3] of Char;
Marker3: Array[0..3] of Char;
Fixed1: LongInt;
FormatTag: Word;
Channels: Word;
SampleRate: LongInt;
BytesPerSecond: LongInt;
BytesPerSample: Word;
BitsPerSample: Word;
Marker4: Array[0..3] of Char;
DataBytes: LongInt;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
fl: file of TWaveHeader;
fl3: file of TWaveHeader;
WaveHeader: TWaveHeader;
WaveHeader2: TWaveHeader;
WaveHeader3: TWaveHeader;
header:integer;
header2:integer;
header3:integer;
Buffer: pbyte;
I:longint;
c: longint;
v:longint;
begin
v:=0;
assignfile(fl, 'C:\bp.wav'); //Получаем заголовок файла
reset(fl);
read(fl, WaveHeader);
closefile(fl);
assignfile(fl, 'C:\SuJ.wav'); //Получаем заголовок файла
reset(fl);
read(fl, WaveHeader3);
closefile(fl);
GetMem(Buffer, WaveHeader.DataBytes);//Резервируем буфер для одной записи
header:=FileOPen('C:\SuJ.wav', fmOpenRead);
header3:=FileOPen('C:\bp.wav', fmOpenRead);
header2:=FileCreate('C:\magawave.wav', fmOpenWrite);
//Перекачиваем параметры
WaveHeader2.Marker1 := WaveHeader.Marker1 ;
WaveHeader2.BytesFollowing:=WaveHeader.BytesFollowing+WaveHeader3.BytesFollowing;
WaveHeader2.Marker2 := WaveHeader.Marker2;
WaveHeader2.Marker3 := WaveHeader.Marker3;
WaveHeader2.Fixed1 := WaveHeader.Fixed1;
WaveHeader2.FormatTag := WaveHeader.FormatTag;
WaveHeader2.SampleRate := WaveHeader.SampleRate;
WaveHeader2.Channels := WaveHeader.Channels;
WaveHeader2.BytesPerSecond := WaveHeader.BytesPerSecond;
WaveHeader2.BytesPerSample:=WaveHeader.BytesPerSample;
WaveHeader2.BitsPerSample := WaveHeader.BitsPerSample+WaveHeader3.BitsPerSample;
WaveHeader2.Marker4 := WaveHeader.Marker4;
WaveHeader2.DataBytes := WaveHeader.DataBytes;
v:=filewrite(header2, WaveHeader2, sizeof(WaveHeader2));
//Считываем первый файл
v:=fileseek(header, sizeOf(WaveHeader), 0);
//showmessage(inttostr(v));
c:=round(WaveHeader.BytesFollowing/WaveHeader.DataBytes);
//if c < WaveHeader.BytesFollowing/WaveHeader.DataBytes then c:=c+1;
I:=0;
while i<c do
begin
v:=fileread(header, Buffer^, WaveHeader.DataBytes);
//showmessage(inttostr(i));
v:=filewrite(header2, Buffer^, WaveHeader2.DataBytes);
i:=i+1;
end;
//Считываем второой файл
v:=fileseek(header3, sizeOf(WaveHeader3), 0);
c:=round(WaveHeader3.BytesFollowing/WaveHeader3.DataBytes);
//if c < WaveHeader3.BytesFollowing/WaveHeader3.DataBytes then c:=c+1;
I:=0;
while not(i=c) do
begin
v:=fileread(header3, Buffer^, WaveHeader3.DataBytes);
//showmessage(inttostr(v));
v:=filewrite(header2, Buffer^, WaveHeader2.DataBytes);
//showmessage(inttostr(v));
i:=i+1;
end;
fileclose(header);
fileclose(header3);
fileclose(header2);
end;
function GetFileInfo(Fn:string):string;
var
fl: file of TWaveHeader;
WaveHeader: TWaveHeader;
begin
assignfile(fl, Fn); //Получаем заголовок файла
reset(fl);
read(fl, WaveHeader);
closefile(fl);
GetFileInfo:='Метка №1: '+WaveHeader.Marker1+chr(13)+'Количество байт в файле: '+inttostr(WaveHeader.BytesFollowing)+chr(13)+'Метка №2: '+WaveHeader.Marker2+chr(13)+'Метка №3:'+WaveHeader.Marker3+chr(13)+'Байт в секунду: '+inttostr(WaveHeader.BytesPerSecond)+chr(13)+'Фиксированный: '+inttostr(WaveHeader.Fixed1)+chr(13)+'Тэг формата: '+inttostr(WaveHeader.FormatTag)+chr(13)+'Частота: '+inttostr(WaveHeader.SampleRate)+chr(13)+'Количество каналов: '+inttostr(WaveHeader.Channels)+chr(13)+'Байт в сэмпле: '+inttostr(WaveHeader.BytesPerSample)+chr(13)+'Бит в сэмпле: '+inttostr(WaveHeader.BitsPerSample)+chr(13)+'Метка №4: '+WaveHeader.Marker4+chr(13)+'Байт в блоке: '+inttostr(WaveHeader.DataBytes);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
label1.Caption:=GetFileInfo('C:\bp.wav');
label2.Caption:=GetFileInfo('C:\SuJ.wav');
end;
end.Но к сожалению при воспроизведении созданного файла, проигрывается только Первая часть файла. С чем это может быть связано? |
|
#2
|
||||
|
||||
|
Первое что бросается в глаза
Код:
WaveHeader2.DataBytes := WaveHeader.DataBytes; Код:
WaveHeader2.DataBytes := WaveHeader.DataBytes + WaveHeader3.DataBytes; |
|
#3
|
|||
|
|||
|
Дело в том, что WaveHeader.DataBytes это размер блока данных, он стандартен для всех wav, а за размер отвечает вот это поле WaveHeader.BytesFollowing
|
|
#4
|
||||
|
||||
|
PvP, вы немного напутали с форматом файла, дело в том, что ваше последнее поле DataBytes как раз и есть размер данных wav файла. А вот второе поле BytesFollowing это размер всего файла (или что-то другое, точно не помню уже). Попробуйте сделать как я написал. А вот за размер блока данных отвечает поле Block Align, которого у вас нет, точнее есть, но почему-то называется BytesPerSample.
UPD Вот посидел чуток, все работает. Обработку ошибок сами сделаете. Код:
type
TWaveHeader = record
Marker1 : array [0..3] of Char;
BytesFollowing : LongInt;
Marker2 : Array[0..3] of Char;
Marker3 : Array[0..3] of Char;
Fixed1 : LongInt;
FormatTag : Word;
Channels : Word;
SampleRate : LongInt;
BytesPerSecond : LongInt;
BlockAlign : Word;
BitsPerSample : Word;
Marker4 : Array[0..3] of Char;
DataBytes : LongInt;
end;
procedure JoinWAVEFiles(FileIn1, FileIn2, FileOut : String);
var
f1, f2, fo : TFileStream;
h1, h2, ho : TWaveHeader;
begin
f1 := TFileStream.Create(FileIn1, fmOpenRead);
f2 := TFileStream.Create(FileIn2, fmOpenRead);
f1.Read(h1, SizeOf(h1));
f2.Read(h2, SizeOf(h2));
if (h1.Channels = h2.Channels) and
(h1.SampleRate = h2.SampleRate) and
(h1.BitsPerSample = h2.BitsPerSample) then begin
ho := h1;
ho.BytesFollowing := h1.BytesFollowing + h2.DataBytes;
ho.DataBytes := h1.DataBytes + h2.DataBytes;
fo := TFileStream.Create(FileOut, fmCreate);
fo.Write(ho, SizeOf(ho));
{ f1.Position := SizeOf(h1);
f2.Position := SizeOf(h2); } как-то не обратил внимания, что эти строки можно убрать.
fo.CopyFrom(f1, h1.DataBytes);
fo.CopyFrom(f2, h2.DataBytes);
fo.Free;
end;
f1.Free;
f2.Free;
end;Последний раз редактировалось zip000, 19.05.2008 в 21:24. |