PDA

View Full Version : ادغام دو یا چند فایل wav



babak_delphi
جمعه 06 اردیبهشت 1387, 15:04 عصر
در این مقاله قصد دارم به طور خلاصه نحوه ادغام دو یا چند فایل wav را (مثلا برای پخش روی خط در نرم افزار های تلفن گویا) آموزش دهم
این مقاله را در پاسخ به سوال یکی از دوستان که در تاپیکی با آدرس زیر پرسیده بودند نوشتم
درصورتی که سوالی داشتید مباحث مربوطه را در آن تاپیک مطرح فرمایید
ضمنا خوشحال می شوم اگر دوستان برای بهتر شدن این روش راهنمایی های لازم را مبذول بدارند

http://barnamenevis.org/forum/showthread.php?t=103294


================================================== ===

ابتدا یک متغیر سراسری از نوع Integer به نام fp تعریف کنید
سپس یک فایل با نام دلخواه و در مسیر دلخواه ایجاد کنید
من در این مثال نام فایل را base1_1.wav و مسیر آن را :C در نظر گرفته ام
حال با دستور زیر یک فایل ایجاد می کنیم



fp:=FileCreate('c:\base1_1.wav');


یک متغیر سراسری دیگر به نام len از نوع Integer تعریف می کنیم
در ابتدای فایلی که ایجاد کرده ایم Header فایل را که 58 بایت تول دارد قرار می دهیم




FileWrite(fp,file_header,58);



file_header را در قسمت Const بصورت زیر تعریف می کنیم



file_header : array[0..100]of char =
chr($52)+chr($49)+chr($46)+chr($46)+chr($26)+chr(H 0)+chr(H0)+chr(H0)+chr($57)+chr($41)+chr($56)+chr( $45)+chr($66)+chr($6D)+chr($74)+chr($20)+chr($12)+ chr(H0)+chr(H0)+chr(H0)+chr(H1)+chr(H0)+chr(H1)+ch r(H0)+chr($40)+chr($1F)+chr(H0)+chr(H0)+chr($80)+c hr($3E)+chr(H0)+chr(H0)+chr($02)+chr(H0)+chr($10)+ chr(H0)+chr(H0)+chr(H0)+chr($66)+chr($61)+chr($63) +chr($74)+chr($04)+chr(H0)+chr(H0)+chr(H0)+chr($63 )+chr($E8)+chr(H0)+chr(H0)+chr($64)+chr($61)+chr($ 74)+chr($61)+chr($C6)+chr($D0)+chr(H1)+chr(H0);


این Header در حقیقت فضایی است که برای Header اصلی رزرو کرده ایم
حال تابعی بصورت زیر با نام Merg_file_Wav ایجاد می کنیم



merg_file_wav(fp: Integer; filename: String);


در این تابع fp اشاره گر به فایلی است که ایجاد کرده ایم
filename نام فایلی است که باید به این فایل اضافه شود
کد این تابع نیز بصورت زیر است




procedure merg_file_wav(fp: Integer; filename: String);
var
bufx,buf:array[0..100] of char;
i,fi:Integer;
newlen,lenx:Integer;
Begin
fi:=FileOpen(filename,0);
FileSeek(fi,16,0);
FileRead(fi,buf,4);
lenx:=ord(buf[3]);
lenx:=lenx*256+ord(buf[2]);
lenx:=lenx*256+ord(buf[1]);
lenx:=lenx*256+ord(buf[0]);
FileSeek(fi,lenx,1);
FileRead(fi,bufx,4);
FileRead(fi,buf,4);
//************************************************** **************
buf[0] := chr(ord(buf[0]));
buf[1] := chr(ord(buf[1]));
buf[2] := chr(ord(buf[2]));
buf[3] := chr(ord(buf[3]));
//************************************************** **************
lenx:=ord(buf[3]);
lenx:=lenx*256+ord(buf[2]);
lenx:=lenx*256+ord(buf[1]);
lenx:=lenx*256+ord(buf[0]);
if strpas(bufx)='fact' then
Begin
FileSeek(fi,lenx,1);
FileRead(fi,bufx,4);
FileRead(fi,buf,4);
lenx:=ord(buf[3]);
lenx:=lenx*256+ord(buf[2]);
lenx:=lenx*256+ord(buf[1]);
lenx:=lenx*256+ord(buf[0]);
End;
i:=0;
while i<lenx do
Begin
if (i+100)<lenx then
Begin
FileRead(fi,buf,100);
FileWrite(fp,buf,100);
i:=i+100;
len:=len+100;
End
Else
Begin
FileRead(fi,buf,lenx-i);
FileWrite(fp,buf,lenx-i);
i:=lenx;
len:=len+(lenx-i);
End;
End;
FileClose(fi);
end;




------------------------------------------------------------------------------------------------
در نهایت تابعی به نام set_header بصورت زیر می سازیم




procedure TForm1.set_header;
var
filename,str,strx:String;
cnt,fi,i,i1,i2,ix:Integer;
buf:array[0..100]of char;
b1:Boolean;
begin
b1:=True;
i1:=0;
i2:=i;
FileSeek(fp,54,0);
buf[0]:=chr(len mod 256);
i:=len div 256;
buf[1]:=chr(i mod 256);
i:=i div 256;
buf[2]:=chr(i mod 256);
i:=i div 256;
buf[3]:=chr(i mod 256);
FileWrite(fp,buf,4);
len:=len+50;
FileSeek(fp,4,0);
buf[0]:=chr(len mod 256);
i:=len div 256;
buf[1]:=chr(i mod 256);
i:=i div 256;
buf[2]:=chr(i mod 256);
i:=i div 256;
buf[3]:=chr(i mod 256);
buf[0] := chr(ord(buf[0]));
buf[1] := chr(ord(buf[1]));
buf[2] := chr(ord(buf[2]));
buf[3] := chr(ord(buf[3]));
FileWrite(fp,buf,4);
end;



با این تابع header نهایی را ایجاد می کنیم
خب کار تمام است و شما با استفاده از این روش و طی این مراحل می توانید چند فایل wav را باهم ادغام کنید و مثلا در نرم افزار تلفن گویای خود بکار ببرید
یک بار دیگر این مراحل را مرور می کنیم
ابتدا دو متغیر سراسری از نوع integer با نام های Len و fp ایجاد می کنیم
با استفاده از FileCreate یک فایل خالی در مسیر دلخواه ایجاد می کنیم
با استفاده از Filewrite یک header به طول 58 بایت به ابتدای آن اضافه می کنیم
حال با استفاده از تابع merg_file_wav به ترتیب فایلهایی را که می خواهیم با هم ادغام کنیم ، به فایل جدیدی که ساخته ایم اضافه می کنیم
در نهایت با تابع set_header ، هیدر فایل را ایجاد می کنیم
************************************************** ****************
شما می توانید فایلهایتان را در دیتابیس نگهداری کنید و در مواقع لزوم به ترتیب روی هارد لود کنید و عمل ادغام را انجام دهید
یا اگر فایلهای شما بزرگ هستند و نیاز به سرعت دارید ، می توانید یک بار در ابتدای برنامه فایلها را در RAM بار گذاری کرده و به هر کدام یک نام اختصاص دهید
=================================================
موفق باشید.

B-Vedadian
جمعه 06 اردیبهشت 1387, 17:14 عصر
با تشکر از شما.

:تشویق:فایلهای wav دیگه مثل قدیم فقط با یک فرمت PCM ساده نیستند، تو فایلهای wave اطلاعات فشرده شده به روش Mp3 هم نوشته میشه. علاوه بر اون اگر فقط فرکانس نمونه برداری یا تعداد کانال های موجود تو فایل فرق کنه، نمیشه اطلاعات خام رو کنار هم گذاشت و فقط اندازه هدر رو اصلاح کرد.

اگه میخواید روشتون کلی باشه و یا واضح تر بشه، از msacm و از Windows Multimedia استفاده کنید. یک نمونه کامل با لیسانس آزاد از آقای خجسته تو waveaudio.zip (http://www.delphiarea.com/products/waveaudio/waveaudio.zip) هست که در دلفی قابل استفاده است.

برای منظور خاص مخلوط کردن دو فایل wave سورس WaveStorage.pas رو ببینید.:چشمک:

ali_mohamadi8928
جمعه 06 اردیبهشت 1387, 19:52 عصر
سلام

من کد رو توی پرژه پیاده سازی کردم ... بعد از اداغام دو فایل و ساخت هدر وقتی اومدم فایل رو پخش کنم پخش نشد ....

اقای B-Vedadian من این کامپوننتی که معرفی کردین نصب کردم ... هر چقدر تلاش کردم نتونستم با ابزارهاش دو فایل رو ادغام کنم ... اگه امکانش هست خودتون یک لطفی کنید و یک نمونه با همین کامپوننت درست کنید و همین جا بزارید ... تا به حال چندین مبحث در این رابطه در بخش دلفی ایجاد شده که هیچ کدوم به جواب نرسیده ... اگه شما یک نمونه درست کنید طلسم این کار شکسته میشه ... :خجالت:

babak_delphi
جمعه 06 اردیبهشت 1387, 20:04 عصر
من که گفتم
برای پخش روی خط تلفن
با مدیا پلیر پخش نمیشه
با recordere ویندوز یا cooledit امتحان کنید جواب میده
من دقیقا با همین روش نرم افزار نوشتم و همین الان هم کار میکنه

B-Vedadian
شنبه 07 اردیبهشت 1387, 08:31 صبح
ارسال یک کار آماده الآن برام میسر نیست. اگه با توضیحی که میدم نتونستید کار رو انجام بدید بگید یک مثال کامل بذارم.


var
Wave1, Wave2: TWave;
.
.
.
begin
.
.
.
Wave1.LoadFromFile(...);
Wave2.LoadFromFile(...);
Wave1.ConvertToPCM(Mono16bit44100Hz); // این میتونه هر فرمت دیگه ای باشه
Wave2.ConvertToPCM(Mono16bit44100Hz);
Wave2.Insert(0, Wave1);
Wave2.SaveToFile(...);
.
.
.
end;

:لبخند:

ali_mohamadi8928
شنبه 07 اردیبهشت 1387, 11:39 صبح
سلام دوست عزیز . خوشحالم که توجه داشتی به این مبحث ...

من شیء TWaveStorage رو از اون کامپوننت گذاشتم رو صفحه و یک دکمه ایجاد کردم و کدها رو به صورت زیر توش نوشتم ... برنامه بدون هیچ خطایی اجرا شد ولی وقتی روی دکمه کلیک کردم تا عملیات انجام بشه از اون خطی که قرمزش کردم خطا گرفت و برنامه متوقف شد ... ایا روش دیگری باید به کار ببرم ... ؟ اگه لطف کنید خدتون یک مثال در این زمینه بزارید خیلی خوب میشه ...

http://fire-wizard.persiangig.com/video/Ba-dl.JPG

B-Vedadian
شنبه 07 اردیبهشت 1387, 13:36 عصر
مومن خدا!
باید اشیایی که تو دلفی تعریف میکنی حتما بسازیشون:


// ابتدا
w1 := TWave.Create;
w2 := TWave.Create;
.
.
.

// انتها
w1.Free;
w2.Free;


برای همین سه نقطه گذاشته بودم.

ali_mohamadi8928
شنبه 07 اردیبهشت 1387, 23:02 عصر
سلام ... خیلی ممنونم دوست عزیز ...

باور کن اصلا حواسم نبود .... واقعا اشتباه بیخودی بود ... وقتی این پستت رو دیدم یه لحظه جا خوردم و برگشتم اون عکس رو دیدم بعد تازه دوزاریم افتاد که چه اشتباهی کرده بودم ...

ممنونم