ayub_coder
شنبه 27 خرداد 1391, 20:22 عصر
با سلام خدمت دوستان
بدون حاشیه میرم سر اصل مطلب. یک فایل Wav رو در نظر بگیرید. این فایل چطور به صوت تبدیل میشه؟ می دونم میشه تو دلفی با توابع PlaySound و غیره فایل Wav رو اجرا کرد. ولی سوالم اینجاست پشت پرده ی این تابع چیه؟ چطور یک فایل wav خوانده شد و به صوت تبدیل میشه. آیا تا حالا به صورت low level این کارو کردین؟
منظورم اینه که خودتون فایل رو باز کنید اونو بخونید و به صورت صوت پخش کنید(شاید دید من غلط باشه). امیدوارم منظورم رو گرفته باشین. می خوام بدونم آیا این فایلها خط به خط خوانده شده و به کارت صدا ارسال می شن و کارت صدا اصوات رو تولید می کنه؟ این کار به چه صورته؟ کسی هست منو از این سردرگمی نجات بده؟
loo30fer
یک شنبه 28 خرداد 1391, 09:18 صبح
اگه از کتابخانه Open Source استفاده میکنید تنها کافیه کلید Ctrl رو نگه دارین و روی کلاسش کلیک کنید تا ببینید پشت پرده چه عملیات هایی انجام میشه , اگه در نظر دارین خودتون یک همچین کتابخانه ای رو پیاده سازی کنید بهتره صرف نظر کنید.
ayub_coder
یک شنبه 28 خرداد 1391, 11:16 صبح
چرا باید صرفنظر کنم؟ یعنی این کار اینقدر سخته که تقریبا غیر ممکن باشه؟
Ananas
یک شنبه 28 خرداد 1391, 14:41 عصر
سلام.
چرا باید صرفنظر کنم؟ یعنی این کار اینقدر سخته که تقریبا غیر ممکن باشه؟
یک سری عملیات برای نمایش تصویر و پخش صدا هست که معمولا به شکل سخت افزاری اجرا میشه و موقعی اون رو با نرم افزار شبیه سازی میکنن که سخت افزار کاربر از اجرای اون عملیات پشتیبانی نکنه و سرعت اجرای این طور کارها با سخت افزار خیلی بالا تر از نرم افزار هست. اگه شما می خواید مستقیما داده های صدا رو بنویسید و یا ویرایش کنید و یا به شکل زنده اونهارو برای پخش ارسال کنید باید از چیزی مثل DirectSound استفاده کنید که به شما این امکان رو میده که با سخت افزار با تمام قدرتش کار کنید و در واقع رابط بین برنامه نویس و سخت افزار هست و شما هر جور که دوست داری داده های صدا رو براش ارسال کن (می خوای از فایل لود کن یا اینکه با فرمول ریاضی اونا رو بساز ...) مثلا برنامه های آهنگ سازی ژنراتور هایی برای تولید صدا دارن که با دستورات ریاضی به شکل موج های سینوسی صدا رو تولید میکنن که صدا مجازی هست و کاربر با اعمال تنظیمات لازم روی پلاگین، به صدای مورد نظر میرسه و با ترکیب این ژنراتورها و صداها آهنگ دیجیتالی و مجازی میسازن. DirectSound جزئی از DirectX هست که SDK اون رو میتونید از سایت ماکروسافت دانلود کنید. با XAoudio هم میتونید کار کنید که من اطلاعات زیادی ازش ندارم.
ayub_coder
یک شنبه 28 خرداد 1391, 15:16 عصر
یعنی تابعی مثل PlaySound داره از DirectSound استفاده میکنه؟ یا تابع sndPlaySound مربوط به ویندوز API?
Ananas
یک شنبه 28 خرداد 1391, 17:42 عصر
یکمی خلاصه نویسی میکنم از روی کتاب که ترجمه هلپ دایرکت ایکس:
DirectSound هم برای پخش صدا و هم برای ضبط صدا استفاده میشه و از طریق رابط COM بنام IDirectSound ایجاد شده. و برای کنترل بافرهای صدا و جلوه های 3D رابط هایی رو داره. IDirectSoundCaptur و IDirectSoundCapturBuffer هم برای ضبط صدا استفاده میشه. شما میتونید ابزارهای صدا رو شمارش کنید (بررسی قابلیت های سخت افزار) و با تابع DirectSoundCreate شی DirectSound رو بسازید.
چون ویندوز یک محیط چند برنامه ایه بیشتر از یک برنامه میتونن در یک لحضه بایک راه انداز ابزار کار کنن با استفاده از سطوح تعاونی، DirectX تضمین میکنه که هیچ برنامه ای به ابزار در یک زمان خطرناک یا با یک روش خطرناک ، دسترسی پیدا نخواهد کرد. هر برنامه ی دایرکت ساند یک سطح تعاونی دارد که نحوه دسترسی آن به ابزار را مشخص میکند و برای تعیین سطح تعاونی برنامه از تابع SetCooperativeLevel استفاده میکنید. دایرکت ساند 4 سطح تعاونی برای ابزار های صدا تعریف کرده :عادی، اولویت، انحصاری، نوشتن اولیه.بالاترین سطح تعاونی نوشتن اولیه است که زمانی که برنامه ی شما از این سطح تعاونی استفاده میکند، برنامه ی شما دسترسی مستقیم به بافر اولیه صدا دارد. در این حالت باید مستقیما به بافر اولیه بنویسید.
زمانی که دایرکت ساند رو ایجاد میکنید به طور خودکار یک بافر اولیه ایجاد و مدیریت میشه که برای ترکیب کردن صداها و ارسال اونها به خروجی استفاده میشه. و برنامه شما حداقل باید یک بافر ثانویه داشته باشه که در حین اجرا روی بافر ثانویه مینویسید و ممکنه یک تکه صدا باشه که مکررا پخش میشه . برنامه میتونه صدای ذخیره شده در بافر ثانویه رو بر اساس یک رویداد پخش کنه یا اینکه تو یک حلقه اون رو دائما پخش کنه. وقتی که داده های صدا خیلی بزرگ باشه و روی حافظه جا نشه بافرهای صدا میتونن به عنوان داده های جریانی استفاده بشن یعنی دائما Update بشن. شما در بافرهای ثانویه مینویسید و دایرکت ساند از طریق بافر اولیه اونها رو با هم ترکیب میکنه و در یک لحضه چند صدا رو میتونید با هم ترکیب کنید. ایجاد بافر ثانویه از طریق روال IDirectSound::CreateSoundBuffer انجام میشه. دایرکت ساند دو اشاره گر به داخل بافر را نگهداری میکند یکی موقعیت جاری پخش و دیگری موقعیت نوشتن که مکان نمای نوشتن نامیده میشود.این موقعیت ها در واقع آفست های بایتی به درون بافر هستند و آدرسهای حافضه ی آنها را نمایش نمی دهند.روال IDirectSound::Play همیشه از موقعیت جاری پخش، بافر را پخش میکند. در مورد صدای سه بعدی هم به طور خلاصه با استفاده از دایرکت ساند میتونید صداهای سه بعدی و استریو بسازید و از جلوه های سه بعدی اون برای طبیعی شنیده شدن صدا استفاده کنید که پارامتر هایی برای شبیه سازی اثر دوپلر داره و با تنظیم شدت و فاصله و موقعیت شنونده نسبت به منبع صدا در محیط مجازی سه بعدی، صدای لازم برای بلندگوی چپ و یا راست رو محاسبه میکنه.
______________
اینا رو نوشتم که یه ذهنیتی از دایرکت ساند داشته باشی و تقریبا بدونی قراره چه برنامه هایی بنویسی. کلا از طریق توابع و API های دایرکت ساند می تونی با صدا کار کنی.
بقیشو خودت از کتاب یا هلپ بخون.
ayub_coder
یک شنبه 28 خرداد 1391, 23:12 عصر
ولی منظور من برنامه نویسی سطح پایینه. یعنی نیاز به هیچ کتابخانه ای نباشه. حتی دایرکت ساند. مثلا خود ویندوز چطور یه فایل ساده wav رو پخش میکنه؟ حتما یه کد نویسی سطح پایین داره که فایل رو بایت به بایت می خونه و اون رو به کارت صدا می فرسته. منظورم اینه!
firststep
دوشنبه 29 خرداد 1391, 00:06 صبح
سلام
دربازه کار با کلاسهای زمان اینجا کامل توصیح دادم
tdatatime (http://barnamenevis.org/showthread.php?307679)
موفق باشید
Ananas
دوشنبه 29 خرداد 1391, 00:27 صبح
ببینید مسئله اینه که این کارا نرم افزاری نباید انجام بشه بخاطر سرعت کم نرم افزار (یا بهتر بگیم سرعت زیاد سخت افزار). من فکر میکنم توابع پخش صدای ویندوز هم دارن سخت افزاری کار میکنن. برای کار با سخت افزار شما نیاز دارید به کدهای انجام عملیات سخت افزار، که توسط سازندگان سخت افزار ارائه میشن که بهش میگن HAL . دایرکت ایکس در واقع به خودی خودش سرعت نداره و سرعت اون وابسته به سخت افزاره. انجام هر عمل خاصی ممکنه داخل سخت های مختلف متفاوت باشه و دایرکت ایکس از عملیات درونی اونها اطلاعاعی نداره مثلا روش پخش صدا ممکنه تو سخت افزار های مختلف از شرکت های سازنده مختلف، متفاوت باشه بخاطر همین همه ی سازندگان، یک HAL مشترک رو پیاده سازی میکنن که دایرکت ایکس توسط اون میتونه به عملیات و خصیصه های سخت افزار دسترسی پیدا کنه و توسط توابع اشیای COM در برنامه نویسی اونها رو به برنامه نویس ارائه کنه. در واقع این عملیات خاص و کدهای مشخص کنندشون، یک جور قرار داد و تعامل بین سازندگان سخت افزار و سازندگان نرم افزار(مثلا دایرت ایکس) هست. و اگه شما هم بخواید از این خصیصه ها استفاده کنید و از 0 برنامه پخش صدا و یا نمایش تصویر رو بسازید، باید از کد های خاص سخت افزار اطلاع داشته باشید که تازه در این صورت می تونید چیزی مثل دایرکت ایکس رو بسازید که خوب وقتی هست و امتحانشم پس داده و خیلی درست و اصولی طراحی شده توسط سازندگان متخصص، چه لزومی داره خودتون همچین چیزی بسازید؟
یا اینکه به شکل نرم افزاری بخواید این کار رو انجام بدید که سرعت نرم افزار هیچ موقع به سرعت سخت افزار نمیرسه چون این عملیات خاص به شکل موازی و خیلی بهینه با سخت افزار داره انجام میشه. به فرض که نرم افزاری هم نوشتید و درست هم اجرا شد، حالا مسئله سرعت خیلی مهمه! اگه صدا با سرعت متعادلی پخش نشه و همش وسط کار سکته بزنه و تاخیر های تیکه تیکه داشته باشه اونوقت اصلا به درد نمیخوره. وقتی کاربر هزینه کرده و سخت افزار تهیه کرده انتظار داره که برنامه با قدرت اجرا بشه نه اینکه ضعیف باشه. مثل اینه که سویچ ماشینتو بگیری تو دستت بعد مسیر چند ساعترو پیاده بری! چه کاریه. بهتره از سخت افزار استفاده کنی.
ayub_coder
دوشنبه 29 خرداد 1391, 05:45 صبح
من یک کد پیدا کردم ولی به زبان سی(Borland TurboC )- تستش هم کردم کار می کنه.بدون استفاده از هیچ کتابخانه ای پخش میکنه! ولی درکش خیلی سخته! :متعجب:
Ananas
دوشنبه 29 خرداد 1391, 10:09 صبح
کو؟
.
ayub_coder
دوشنبه 29 خرداد 1391, 10:23 صبح
این فایل wavplay.c
#include "sbwav.c"
void main ()
{
//Check for Sound Blaster
FindSB ();
if (!SBFound ()) {
printf ("Sound Blaster not found.\n");
return;
}
//Initialise Sound Blaster
SBOpen ();
//Play a file
SBPlay ("TEST.WAV");
do; while (SBPlaying () && !kbhit ());
SBStop ();
//Close Sound Blaster
SBClose ();
}
اینم فایل sbwav.c
/************************************************** **************************
** Library to play 8bit uncompressed mono WAV files through the **
** Sound Blaster **
** by Steven H Don **
** **
** For questions, feel free to e-mail me. **
** **
** shd@earthling.net **
** http://shd.cjb.net **
** **
************************************************** **************************/
#include "dos.h"
#include "stdio.h"
#include "stdlib.h"
int SBFound ();
void SBOpen ();
void SBClose ();
void SBPlay (char *FileName);
void SBStop ();
long SBLength ();
int SBPlaying ();
//A WAV header consits of several chunks:
struct
RIFFChunkType {
long RIFF;
long NextChunkSize;
long RIFFType;
} RIFFChunk;
struct
fmtChunkType {
long fmt;
long fmtLength;
short WaveType;
short Channels;
long SampleRate;
long BytesPerSecond;
short BlockAlignment;
short BitResolution;
} fmtChunk;
struct
dataChunkType {
long data;
long dataLength;
} dataChunk;
//Sound Blaster settings
short Base; //Sound Blaster base address
char DMA; //The DMA channel
char IRQ; //The IRQ level
#ifdef __cplusplus
void interrupt (*OldIRQ)(...);
#else
void interrupt (*OldIRQ)();
#endif
//Memory buffer
short RBuffer; //Read buffer indicator
unsigned char *DMABuffer; //Pointer to DMA buffer
short Page;
short Offset;
//File access
FILE *WAVFile;
volatile long ToBeRead; //Amount of samples to be read from file
volatile long ToBePlayed; //Amount of samples to be played
//Global indicator
volatile int Playing;
/************************************************** **************************
** Checks to see if a Sound Blaster exists at a given address, returns **
** true if Sound Blaster found, false if not. **
************************************************** **************************/
int ResetDSP (short Test)
{
//Reset the DSP
outportb (Test + 0x6, 1);
delay (10);
outportb (Test + 0x6, 0);
delay (10);
//Check if (reset was succesfull
if (((inportb (Test + 0xE) & 0x80) == 0x80) && (inportb (Test + 0xA) == 0xAA))
{
//DSP was found
Base = Test;
return 1;
}
//No DSP was found
return 0;
}
/************************************************** **************************
** Send a byte to the DSP (Digital Signal Processor) on the Sound Blaster **
************************************************** **************************/
void WriteDSP(unsigned char Value)
{
//Wait for the DSP to be ready to accept data
while ((inportb (Base + 0xC) & 0x80) == 0x80);
//Send byte
outportb (Base + 0xC, Value);
}
/************************************************** **************************
** The DMA controller is programmed with a block length of 32K - the **
** entire buffer. The DSP is instructed to play blocks of 16K and then **
** generate an interrupt (which allows the program to load the next part **
** that should be played). **
************************************************** **************************/
void AutoInitPlayback ()
{
outportb (0x0A, 4 | DMA); //Mask DMA channel
outportb (0x0C, 0); //Clear byte pointer
outportb (0x0B, 0x58 | DMA); //Set mode
outportb (DMA << 1, Offset & 0xFF); //Write the offset to the DMA controller
outportb (DMA << 1, Offset >> 8); //Write the offset to the DMA controller
/*
The mode consists of the following:
0x58+x = binary 01 01 10 xx
| | | |
| | | +- DMA channel
| | +---- Read operation (the DSP reads from memory)
| +------- Auto init mode
+---------- Block mode
*/
//Write the page to the DMA controller
switch (DMA) {
case 0 : outportb (0x87, Page);
break;
case 1 : outportb (0x83, Page);
break;
case 3 : outportb (0x82, Page);
break;
}
outportb ((DMA << 1) + 1, 0xFF); //Set the block length to 0x7FFF = 32 Kbyte
outportb ((DMA << 1) + 1, 0x7F);
outportb (0x0A, DMA); //Unmask DMA channel
WriteDSP (0x48); //Set the block length to 0x3FFF bytes = 16 Kbyte
WriteDSP (0xFF);
WriteDSP (0x3F);
WriteDSP (0x1C); //DSP-command 1Ch - Start auto-init playback
}
void SingleCyclePlayback ()
{
short BufOfs;
ToBePlayed--;
BufOfs = Offset + (RBuffer << 14);
outportb (0x0A, 4 | DMA); //Mask DMA channel
outportb (0x0C, 0); //Clear byte pointer
outportb (0x0B, 0x48 | DMA); //Set mode
outportb (DMA << 1, BufOfs & 0xFF); //Write the offset to the DMA controller
outportb (DMA << 1, BufOfs >> 8); //Write the offset to the DMA controller
/*
The mode consists of the following:
0x48+x = binary 01 00 10 xx
| | | |
| | | +- DMA channel
| | +---- Read operation (the DSP reads from memory)
| +------- Single cycle mode
+---------- Block mode
*/
//Write the page to the DMA controller
if (DMA == 0) outportb (0x87, Page);
if (DMA == 1) outportb (0x83, Page);
if (DMA == 3) outportb (0x82, Page);
//Set the block length
outportb ((DMA << 1) + 1, ToBePlayed & 0xFF);
outportb ((DMA << 1) + 1, ToBePlayed >> 8);
outportb (0x0A, DMA); //Unmask DMA channel
//DSP-command 14h - 8bit single cycle playback
WriteDSP (0x14);
WriteDSP (ToBePlayed & 0xFF);
WriteDSP (ToBePlayed >> 8);
//Nothing left to play
ToBePlayed = 0;
}
/************************************************** **************************
** Loads one half of the DMA buffer from the file **
************************************************** **************************/
void ReadBuffer (short Buffer)
{
//If the remaining part of the file is smaller than 16K,
//load it and fill out with silence
if (ToBeRead <= 0) return;
if (ToBeRead < 16384) {
memset (DMABuffer + (Buffer << 14), 128, 16384);
fread (DMABuffer + (Buffer << 14), 1, ToBeRead, WAVFile);
ToBeRead = 0;
} else {
fread (DMABuffer + (Buffer << 14), 1, 16384, WAVFile);
ToBeRead -= 16384;
}
}
/************************************************** **************************
** IRQ service routine - this is called when the DSP has finished playing **
** a block **
************************************************** **************************/
#ifdef __cplusplus
void interrupt ServiceIRQ (...)
#else
void interrupt ServiceIRQ ()
#endif
{
//Relieve DSP, 8bit port
inportb (Base + 0xE);
//Acknowledge hardware interrupt
outportb (0x20, 0x20);
//Acknowledge cascade interrupt for IRQ 2, 10 and 11
if (IRQ == 2 || IRQ == 10 || IRQ == 11) outportb (0xA0, 0x20);
//Take appropriate action for buffers
if (Playing) {
ToBePlayed -= 16384;
if (ToBePlayed > 0) {
ReadBuffer (RBuffer);
if (ToBePlayed <= 16384) {
RBuffer ^= 1;
SingleCyclePlayback ();
} else if (ToBePlayed <= 32768) {
WriteDSP (0xDA);
}
} else {
Playing = 0;
}
}
RBuffer ^= 1;
}
/************************************************** **************************
** This procedure allocates 32K of memory to the DMA buffer and makes sure **
** that no page boundary is crossed **
************************************************** **************************/
void AssignBuffer ()
{
unsigned char *TempBuf; //Temporary pointer
long LinearAddress;
short Page1, Page2;
//Assign 32K of memory
TempBuf = (char *)malloc (32768);
//Calculate linear address
LinearAddress = FP_SEG (TempBuf);
LinearAddress = (LinearAddress << 4) + FP_OFF (TempBuf);
//Calculate page at start of buffer
Page1 = LinearAddress >> 16;
//Calculate page at end of buffer}
Page2 = (LinearAddress + 32767) >> 16;
//Check to see if a page boundary is crossed
if (Page1 != Page2) {
//If so, assign another part of memory to the buffer
DMABuffer = (char *)malloc(32768);
free (TempBuf);
} else //otherwise, use the part we've already allocated
DMABuffer = TempBuf;
//Convert pointer to linear address}
LinearAddress = FP_SEG (DMABuffer);
LinearAddress = (LinearAddress << 4) + FP_OFF (DMABuffer);
Page = LinearAddress >> 16;
Offset = LinearAddress & 0xFFFF;
}
/************************************************** **************************
** This procedure checks the possible addresses to see whether a Sound **
** Blaster is installed. **
************************************************** **************************/
void FindSB ()
{
char Temp;
char *BLASTER;
//Nothing found yet
Base = 0;
//Check for Sound Blaster, address: ports 210, 220, 230, 240, 250, 260 or 280
for (Temp = 1; Temp < 9; Temp++) {
if (Temp != 7)
if (ResetDSP (0x200 + (Temp << 4))) {
break;
}
}
if (Temp == 9) return;
//Search for IRQ and DMA entry in BLASTER environment string
BLASTER = getenv ("BLASTER");
DMA = 0;
for (Temp = 0; Temp < strlen (BLASTER); Temp++)
if ((BLASTER [Temp] | 32) == 'd')
DMA = BLASTER [Temp + 1] - '0';
for (Temp = 0; Temp < strlen (BLASTER); Temp++)
if ((BLASTER [Temp] | 32) == 'i') {
IRQ = BLASTER [Temp + 1] - '0';
if (BLASTER [Temp + 2] != ' ')
IRQ = IRQ * 10 + BLASTER [Temp + 2] - '0';
}
}
/************************************************** **************************
** This procedure sets up the program according to the values in IRQ and **
** DMA. **
************************************************** **************************/
void InitIRQandDMA ()
{
//Save old IRQ vector
if (IRQ == 2 || IRQ == 10 || IRQ == 11) {
if (IRQ == 2) OldIRQ = getvect (0x71);
if (IRQ == 10) OldIRQ = getvect (0x72);
if (IRQ == 11) OldIRQ = getvect (0x73);
} else OldIRQ = getvect (8 + IRQ);
//Set new IRQ vector
if (IRQ == 2 || IRQ == 10 || IRQ == 11) {
if (IRQ == 2) setvect (0x71, ServiceIRQ);
if (IRQ == 10) setvect (0x72, ServiceIRQ);
if (IRQ == 11) setvect (0x73, ServiceIRQ);
} else setvect (8 + IRQ, ServiceIRQ);
//Enable IRQ
if (IRQ == 2 || IRQ == 10 || IRQ == 11) {
if (IRQ == 2) outportb (0xA1, inportb (0xA1) & 253);
if (IRQ == 10) outportb (0xA1, inportb (0xA1) & 251);
if (IRQ == 11) outportb (0xA1, inportb (0xA1) & 247);
outportb (0x21, inportb (0x21) & 251);
} else outportb (0x21, inportb (0x21) & !(1 << IRQ));
}
/************************************************** **************************
** This procedure releases the DMA channel and IRQ level **
************************************************** **************************/
void ReleaseIRQandDMA ()
{
//Free interrupt vectors used to service IRQs
if (IRQ == 2 || IRQ == 10 || IRQ == 11) {
if (IRQ == 2) setvect (0x71, OldIRQ);
if (IRQ == 10) setvect (0x72, OldIRQ);
if (IRQ == 11) setvect (0x73, OldIRQ);
} else setvect (8 + IRQ, OldIRQ);
//Enable IRQ
if (IRQ == 2 || IRQ == 10 || IRQ == 11) {
if (IRQ == 2) outportb (0xA1, inportb (0xA1) | 2);
if (IRQ == 10) outportb (0xA1, inportb (0xA1) | 4);
if (IRQ == 11) outportb (0xA1, inportb (0xA1) | 8);
outportb (0x21, inportb (0x21) | 4);
} else outportb (0x21, inportb (0x21) | (1 << IRQ));
}
/*----------------------------------------------------------------------------
EXTERNALLY VISIBLE FUNCTIONS
*/
/************************************************** **************************
** This procedure returns true if the Sound Blaster is present. **
************************************************** **************************/
int SBFound ()
{
return Base != 0;
}
/************************************************** **************************
** This procedure initialises the Sound Blaster **
************************************************** **************************/
void SBOpen ()
{
//Set up IRQ and DMA channels
InitIRQandDMA ();
//Assign memory to the DMA Buffer
AssignBuffer ();
//Set read buffer to first buffer
RBuffer = Playing = 0;
}
/************************************************** **************************
** This procedure gracefully shuts down the unit. **
************************************************** **************************/
void SBClose ()
{
//Stop any operation in progress
if (Playing) SBStop ();
//Release the memory buffer
free (DMABuffer);
//Release the IRQ and DMA channels
ReleaseIRQandDMA ();
}
/************************************************** **************************
** Starts playing a WAV file. **
************************************************** **************************/
void SBPlay (char *FileName)
{
long Before;
//Don't play if there's no buffer
if (!DMABuffer) return;
//Start playback in buffer 0 and clear the buffer
RBuffer = 0;
memset (DMABuffer, 0, 32768);
//Open the file for output
WAVFile = fopen (FileName, "rb");
if (!WAVFile) return;
//Read RIFF chunk
fread (&RIFFChunk, sizeof (RIFFChunk), 1, WAVFile);
if (RIFFChunk.RIFF != 0x46464952 || RIFFChunk.RIFFType != 0x45564157) {
fclose (WAVFile);
return;
}
//Read fmt chunk
do {
Before = ftell (WAVFile);
fread (&fmtChunk, sizeof (fmtChunk), 1, WAVFile);
fseek (WAVFile, Before + fmtChunk.fmtLength + 8, SEEK_SET);
} while (fmtChunk.fmt != 0x20746D66);
//Set playback frequency
WriteDSP (0x40);
WriteDSP (256 - 1000000 / fmtChunk.SampleRate);
//Read data chunk
do {
Before = ftell (WAVFile);
fread (&dataChunk, sizeof (dataChunk), 1, WAVFile);
if (dataChunk.data != 0x61746164)
fseek (WAVFile, Before + dataChunk.dataLength + 8, SEEK_SET);
} while (dataChunk.data != 0x61746164);
ToBeRead = ToBePlayed = dataChunk.dataLength;
//DSP-command D1h - Enable speaker
WriteDSP (0xD1);
//Read first bit of data
ReadBuffer (0);
ReadBuffer (1);
if (ToBeRead > 0) AutoInitPlayback ();
else SingleCyclePlayback ();
Playing = 1;
}
/************************************************** **************************
** Stops playback **
************************************************** **************************/
void SBStop ()
{
//Stops DMA-transfer
WriteDSP (0xD0);
//Playback has completed
Playing = 0;
//Close the file
fclose (WAVFile);
}
/************************************************** **************************
** This procedure returns the length of the WAV file in whole seconds. **
************************************************** **************************/
long SBLength ()
{
return dataChunk.dataLength / fmtChunk.BytesPerSecond;
}
/************************************************** **************************
** This procedure returns true if the WAV is still playing. **
************************************************** **************************/
int SBPlaying ()
{
return Playing;
}
Ananas
دوشنبه 29 خرداد 1391, 13:25 عصر
دستت درد نکنه. منم خیلی هالیم نشد چی به چیه.
فایل پاسکال مشابه هم تو آدرس زیر هست:
http://www.programmersheaven.com/mb/pasprog/346832/346967/re-playing-multiple-wav-files-simultaneously/?S=B20000
چند سال پیش هم همچین کدی تو اینترنت پیدا کرده بودم که امتحانش کردم سرعتش کم بود. اون هم مثل این کدها بود. فرکانس و ریت و ازینجور چیزا داشت.
ولی بازم من نظرم اینه که استفاده از DirectSound بهتر و مطمئن تر از همه ی ایناست.
ayub_coder
دوشنبه 29 خرداد 1391, 14:15 عصر
منم نمی خوام به صورت عملی ازش استفاده کنم که! فقط می خواستم بدونم اینکار چطور انجام میشه! در سطح پایین! حالا تقریبا یه چیزایی حالیم شد. ولی نه کاملا! :لبخند:
برای ساختن یک پلیر که بتونه فایلهای MP3 و غیره رو هم بخونه باید از همین دایرکت ساند استفاده کرد؟
Ananas
دوشنبه 29 خرداد 1391, 14:35 عصر
دایرکت ساند روالی برای کار با فایل هایی غیر از wav نداره ولی شنیدم XAoudio داره. و شما برای mp3 یا خودتون باید کد خارج کردن از حالت فشرده و تبدیل اون به wav رو انجام بدین یا از کتابخونه خاصی برای این کار استفاده کنید. راستی OpenAL هم برای کار با صدا هست. از اون هم میتونی استفاده کنی. سمپل های دایرکت ساند رو که همراه DirectX_SDK هست ببینی احتمالا تو اونها نمونه برای استفاده از mp3 باشه الان یادم نیست مطمئن نستم.
ayub_coder
دوشنبه 29 خرداد 1391, 14:45 عصر
پس باید برای MP3 هم خودم دست بکار شم و یه نسخه سطح پایین پیدا کنم :چشمک:
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.