سلام
خب این برنامهای هست که قولش رو داده بودم تا به فرمت دلخواه صدا را ضبط کنید. آن هم به شکلی خیلی ساده.
راههای زیادی برای رسیدن به ضبط صدا هست! اما هدف من در اینجا ضبط صدا به فرمت دلخواه است، مثلا mp3 و بدون استفاده از ابزارهای برنامهنویسی نظیر ActiveX و ...
ما میخواهیم با استفاده از توابع API به این هدف برسیم. توابع در دسترس برای پخش و ضبط صدا عبارتند از mciSendString، mciSendCommand و mciExecute. (برای آشنا شدن با این توابع میتوانید به سراغ MSDN بروید.)
این توابع هر کدام پیچیدگی خاص خودشان را دارند. مخصوصا اگر قصد ضبط صدا را داشته باشید که باید پارامترهای زیادی را تنظیم کنید که نرخنمونه برداری، تعداد کانال صوتی، بافر و ... را شامل میشوند.
من قصد دارم شما را با تابع mciSendCommand آشنا کنم که با وجود پیچیدگی بیش از حد، استفاده راحتتری از آن هم میسر هست و البته به طریقی که آموزش میدهم.
بهتر هست با یک مثال شروع کنیم:
شکل کلی این تابع این چنین هست:
Public Declare Function mciSendCommand Lib "winmm.dll" _
Alias "mciSendCommandA" (ByVal wDeviceID As Long, _
ByVal uMessage As Long, _
ByVal dwParam1 As Long, _
ByVal dwParam2 As Any) As Long
پخش فایل صوتی شامل چند مرحله است:
1- باز کردن فایل صوتی
2- دستور پخش
3- بستن فایل (که حتما باید انجام بشه)
باز کردن فایل صوتی خود شامل پارامترهایی است که در ساختار زیر مشخص میشود:
Private Type MCI_OPEN_PARMS
dwCallback As Long
wDeviceID As Long
lpstrDeviceType As String
lpstrElementName As String
lpstrAlias As String
End Type
Dim dwReturn As Long
Dim mciOpenParms As MCI_OPEN_PARMS
'Open a waveform-audio device with filename for play.
mciOpenParms.lpstrDeviceType = "WaveAudio"
mciOpenParms.lpstrElementName = filename dwReturn = mciSendCommand(0, MCI_OPEN, _
MCI_OPEN_ELEMENT Or MCI_OPEN_TYPE, _
mciOpenParms)
If dwReturn Then
MsgBox "Failed to open device; don't close it, just return error."
Exit Sub
End If 'The device opened successfully; get the device ID.
wDeviceID = mciOpenParms.wDeviceID
و برای پخش از کد زیر استفاده میکنیم که بعد از کد باز کردن فایل میگذاریم:
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, 0, vbNull)
If dwReturn Then
mciSendCommand wDeviceID, MCI_Close, 0, vbNull
MsgBox "MCI_PLAY not succed!"
Exit Sub
End If
اگر دقت کنید پارامتر سوم مقدار صفر را داراست. این پارامتر میتواند به نحوی مشخص شود که با اجرای دستور پخش، کنترل به برنامه داده شود یا تا زمانی که پخش به اتمام نرسیده برنامه منتظر بماند. و مشخههای دیگر.
چون ذکر نکردیم پس کنترل برنامه را در حین پخش در دست میگیریم.
و سرانجام با این کد فایل را میبندیم:
Dim dwReturn As Long dwReturn = mciSendCommand(wDeviceID, MCI_Close, MCI_WAIT, vbNull)
If dwReturn Then
mciSendCommand wDeviceID, MCI_Close, 0, vbNull
MsgBox "MCI_Close not succed!"
Exit Sub
End If
و اما ضبط صدا. برای ضبط باید از ساختار پیچیده زیر استفاده کنیم:
Private Type MCI_WAVE_SET_PARMS
dwCallback As Long
dwTimeFormat As Long
dwAudio As Long
wInput As Long
wOutput As Long
wFormatTag As Integer
wReserved2 As Integer
nChannels As Integer
wReserved3 As Integer
nSamplesPerSec As Long
nAvgBytesPerSec As Long
nBlockAlign As Integer
wReserved4 As Integer
wBitsPerSample As Integer
wReserved5 As Integer
End Type
برای یک ضبط ساده باید این همه پارامتر را مقدار دهی کنید و تازه ممکن است صدا بر اساس مقادیر اشتباه بی کیفیت و نامطلوب ضبط شود.
از همه اینها که بگذریم قصد من این بود تا ترفندی را به شما آموزش بدهم که خیلی راحت صدا را به هر فرمتی که خواستید ضبط کنید.
.:: CODEC ::.
این کلمه مخفف واژههای COmpress/DECompress هست و به زبان سادهتر درایوری است که عمل کدسازی و دیکودسازی اطلاعات را انجام میدهد، البته برای کاربر محسوس نیست و به نوعی در پشت پرده انجام میگیرد.
وقتی شما فایلهای wav را در سیستم پخش میکنید، باید codec فایلهای wav در سیستم نصب شده باشد وگرنه قادر به پخش نیستید که البته بهمراه ویندوز این درایورها نصب میشوند.
برای فایلهای mp3 نیز همین قضیه صادق هست و غیره.
برای اینکه بدانید بر روی سیستم شما چه codecهایی نصب شده مراحل زیر را دنبال کنید:
Control Panel -> Sound & Audio Device -> Hardware -> select Audio Codec from list -> click on Properties.
با این توضیحاتی که آمد میخواهیم بر اساس یکی از codecهای نصب شده اقدام به ضبط صدا کنیم.
لازم به ذکر است که برخی codecها فقط حاوی بخش پخش هستند و امکان ضبط رو ندارند!
برسیم به هدف اصلی از این صحبتها.
1- Sound Recorder ویندوز رو باز کنید و سپس از منوی File گزینه Save As... را انتخاب کنید.
2- دکمه Change را کلیک کنید تا لیست codec ها ظاهر شود.
3- گزینه Format را با codecی که میخواهید تنظیم کنید.
4- OK کنید و بعد نام فایل را مشخص کنید و Save نمائید.
با طی این 4 مرحله شما یک فایل صوتی ساختید که فقط حاوی تنظمیات صدا است. یعنی تمام پارامترهای ساختار MCI_WAVE_SET_PARMS
حالا اگر با تابع mciSendCommand این فایل را باز کنید و اقدام به ضبط صدا نمائید، در واقع دارید به فرمتی که میخواهید صدا را ضبط میکنید و درگیر تنظیمات خاصی نیستید.
سورسی را که مربوط به همین بخش است، این صحبتها را پیادهسازی کرده و نمونه کاملی از ضبط و پخش به فرمت دلخواه را انجام میدهد.
و این نکته که دو فایل با پسوند mrf در کنار برنامه هست، در واقع فایلهای حاوی ساختار هستند(wav) که پسوندشان عوض شده.
برنامه ابتدا لیست تمام فایلهای با پسوند mrf را لیست میکند و در هنگام ضبط به همان فرمتی که انتخاب میکنید اقدام به ضبط میکند.
شما میتوانید هر ساختاری را که دوست داشتید با Sound Recorder بسازید و با پسوند mrf در کنار برنامه ذخیره کنید و از نزدیک با چگونگی عمل ضبط آشنا شوید.
امیدوارم که مفید واقع شده باشه
اگر سوالی بود حتما بپرسید.
موفق باشید
جوئل اسپولسکی بنیانگذار Fog Creek Software است که یک شرکت کوچک نرم افزاری در شهر نیویورک است.او فارغ التحصیل دانشگاه یل(Yale University) است وبه عنوان برنامه نویس و مدیر در مایکروسافت ،Viacom و Juno کارکرده است.
جوئل مقاله جالبی در باب کد نویسی داره که با عنوان ۱۲ راه برای کد بهتر است.
مقاله به فارسی ترجمه شده و توصیه میکنم که حتما مطالعه بفرمائید. من خودم هر از گاهی از اول اون رو میخونم تا راهکارهای توصیه شده از ذهنم محو نشه.
برقرار باشید.
بعنوان یک زبان برنامهنویسی با توسعه سریع، ویژوال بیسیک نظر خیلی از برنامهنویسان را از جهت سادگی به خود معطوف کرد. برنامهنویسی با ویژوال بیسیک در کمترین زمان صورت میگیرد حال آنکه در مقابل زبانهایی چون C و ++C اغلب اوقات به روزها کار مفید نیاز است.
اما بیشترین انتقادی که برنامهنویسان از ویژوال بیسیک دارند در این است که قادر به تولید کتابخانههای پویا (DLL) نیست. حقیقتا این نظر مورد قبول است که نمیتوان این نوع فایلها را در کنار فایلهای اجرایی(Exe) یا ActiveX Exe تولید کرد.
در این مقاله ما قصد داریم که نگاه دقیقی به نحوه تولید فایلهای اجرایی در ویژوال بیسیک یندازیم و بعد با طی مراحل سادهای موفق به ایجاد فایلهای DLL بشویم تا از زیر بار این انتقاد نیز رهایی یابیم.
قبلا به این موضوع اشاره شد که فایهای DLL آن دست از برنامههایی هستند که یکبار نوشته میشوند و در پروژههای بعدی بکرات میتواند از آنها استفاده برد. چیزی که هسته ویندور را تشکیل میدهد اینگونه فایلها هستند. علاوه بر آن تکنیکهایی وجود دارد که شما را قادر میسازد تا برنامههایی بنویسید که قادرند خود را بروز برسانند و یا خود ترمیم باشند. بهتر از آن اینکه برنامهای بنویسید که با الحاق اینگونه فایلها بدان قدرت و امکانات جدید بدان افزود. همانند نرمافزارهای رایج از جمله Winamp.
کتابخانههای پویای قابل اتصال (DLL) چه هستند؟
یک DLL مجموعهای از توابع و پروسههایی است که میتواند از برنامه یا DLLهای نظیر خود فراخوانده شود.
استفاده از اینگونه کتابخانههای دو مزیت اصلی دارد:
1- امکان به اشتراک گذاری از کد را فراهم میسازند. یک DLL میتواند مورد استفاده خیلی از برنامههای قرار گیرد. بعنوان مثال کتابخانه Win32 API نمونهای از این سری فایلها است. بعلاوه از زمانی که پروسههای گوناگون قادر به فراخوانی یک DLL واحد هستند امکان به اشتراک گذاری کدها و روتینها فراهم آمده است. یک فایل DLL تنها یکبار به درون حافظه لود میشود و بارها توسط پروسههای گوناگونی مورد استفاده قرار میگیرد و این یعنی مدیریت حافظه بهتر.
2- مزیت دیگر امکان نوشتن برنامهها بصورت اجزای منفصل است که این اجزا خود قابل تعویض با نگارشهای جدیدتر جهت توسعه نرمافزار خواهند بود بدون اینکه خطی از کد برنامه اصلی دگرگون شود.
با این توصیف فایلهای کتابخانهای درونی که در پروژههای مورد استفاده قرار میگیرد در صورت تغییر نیاز هست تا پروژه اصلی دوباره کمپایل شود تا بتوان با آن ارتباط بر قرار کرد. اما در DLL ها چون بصورت پویا و قابل انعطاف نوشته شدهاند این اتصال در بیرون از بدنه اصلی و درست در زمان فراخوانی آن قبیل از متدها و توابع شکل میگیرد و این خود تفاوت آشکار از مزیت این گونه از فایلها میباشد.همچنین یک فایل DLL میتواند حاوی توابعی باشد که فقط مورد استفاده خود هست و از درون به آن دسترسی نخواهیم داشت و آندسته از تابعی را که نیاز هست معرفی میکنیم تا از بیرون بدان دسترسی داشته باشیم. در این مرحله نیاز به معرفی در فایلهای Def هست که در پروژههای C و C++ مورد استفاده قرار میگیرد.
و اما ساختار DLL
فایلهای DLL حاوی یک مدخل شروع انتخابی (optional entry point) و پایانی هستند که در زمانی که توسط برنامههای دیگر به درون حافظه لود یا آنلود میشوند قابل اجرا است. ویندوز این پروسه را در زمانی که یک برنامه DLLها را بدرون حافظه لود یا آنلود میکند اجرا میکند.
این دو نوع پروسه به DLL این امکان را میدهد که یک سری از مقدمات را پیش از استفاده مهیا کند یا بعد از استفاده پاکسازی نماید. در ویژال بیسیک این تابع بدین گونه تعریف میشود:
Public Function DllMain(hinstDLL As Long, fdwReason As Long , lpwReserved As Long) As Boolean
که پارامترهای آن بدین قرارند:
hInstDLL که حاوی یک مقدار یکتا بعنوان دستگیره فایل DLL است.
fdwReason مشخص کننده دلیل فراخوانی این پروسه توسط سیستمعامل است که یکی از چهار مقدار زیر را به خود منتصب میکند:
DLL_PROCESS_ATTACH (1): یک پروسه در حال لود DLL به دورن حافظه است. هر پیشنیاز باید در اینجا شکل گیرد.
DLL_THREAD_ATTACH (2): یک ریسمان (Thread) برای این DLL در حال تولید است. هر پیشنیاز برای ایجاد ریسمان در این مرحله میتواند شکل بگیرد.
DLL_THREAD_DETACH (3) ریسمان در حال پایان یافتن است. به منظور پاکسازی DLL از حافظه.
DLL_PROCESS_DETACH (0) فایل DLL در حال خروح از حافظه است. بمنظور پاکسازی سایر کارها توسط برنامهنویس امکان انجام در این مرحله فراهم آمده است.
lpvReserved: حاوی مقدار اضافی در استفاده از DLL_PROCESS_ATTACH یا DLL_PROCESS_DETACH میباشد.
مقدار برگشتی تابع DllMain در هنگام صدا زدن بصورت DLL_PROCESS_ATTACH مقدار TRUE را باید به خود بگیرد.
در تلاش برای تولید و توسعه یک DLL نمونه قصد این را داریم که یک کتابخانه ریاضی تشکیل دهیم. کد زیر در ماژولی بنام MathLib.Bas قرار میگیرد:
Option Explicit
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3
Public Function DllMain(hInst As Long, fdwReason As Long, lpvReserved As Long) As Boolean
Select Case fdwReason
Case DLL_PROCESS_DETACH
' No per-process cleanup needed
Case DLL_PROCESS_ATTACH
DllMain = True
Case DLL_THREAD_ATTACH
' No per-thread initialization needed
Case DLL_THREAD_DETACH
' No per-thread cleanup needed
End Select
End Function
Public Function Increment(var As Integer) As Integer
If Not IsNumeric(var) Then Err.Raise 5
Increment = var + 1
End Function
Public Function Decrement(var As Integer) As Integer
If Not IsNumeric(var) Then Err.Raise 5
Decrement = var - 1
End Function
Public Function Square(var As Long) As Long
If Not IsNumeric(var) Then Err.Raise 5
Square = var ^ 2
End Function