|
#1
|
|||
|
|||
Слияние Wav
Здравствуйте, мне нужно слить два файла 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; Не профи, но и не чайник . D6 - лучше не придумали. Пока. |
#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; Не профи, но и не чайник . D6 - лучше не придумали. Пока. Последний раз редактировалось zip000, 19.05.2008 в 21:24. |