PDA

View Full Version : سوال: مفهوم این قطعه کد چیه ؟



voiceoffox
دوشنبه 01 آذر 1389, 20:53 عصر
این کد {نمیدونم چه طوری} تولید صدا می کنه ! یعنی کارش اینه که صدا بسازه. :تشویق:

اگه می شه بگیرین استفاده ازش بکنین و ببینین چه طور صدا می سازه ! :بامزه:

البته من اینو رو 5 تا کامپیوتر امتحان کردم که رو 3 تاش کار کرد . خیلی عجیبه ! :متعجب:
گاهی اجرا میشه گاهی نمیشه ! تازه، گاهی صدا از بلنگو میاد و یه وقتایی از کارت صدا تازه بعضی موقع ها هم نمی یاد !!! :گریه:

این برنامه رو خودم تو قسمت <مجموعه برنامه های نوشته شده به زبان سی و سی پلاس پلاس> گذاشتم ولی نمیدونم چه جوریه قضیش !!!

حالا میشه بهم بگین چرا گاهی کار میکنه و گاهی نه ! و اصن چه طوری کار می کنه !؟ :گیج:


#include <stdlib.h>
#include <conio.h>
void sound(int f);
main(){
while(!kbhit())
sound(100+random(1000));
}
void sound(int f){
char p;
union{
long d;
char c[2];
}count;
count.d=1193280/f;
outportb(67,182);
outportb(66,count.c[0]);
outportb(66,count.c[1]);
p=inportb(97);
outportb(97,p|3);
for(long delay=0;delay<10000000;delay++);
outportb(97,p);
}

Saeed_m_Farid
چهارشنبه 03 آذر 1389, 12:37 عصر
چرا اینقدر دست و پا میزنی؟ :گیج: ریلکس ریلکس :چشمک:
شما اول بگین با چی این کد رو کامپایل کردین؟ 5 تا کامپیوتر OS شون چی بوده؟
این برنامه اصولاً باید فقط رو OS های 16 بیتی (و اونهایی که با 16 بیتی سازگارند) کار کنه، بعدش هم جسارتاً خیلی کدهای مزخرفی هستند؛ چون از پورت های ثابت (ناشناس حداقل برای من) اونهم با دستورات 16 بیتی یا DOS ای! داره استفاده میکنه؛ برای delay هم که از for ده میلیونی! اونهم بدون اینتراپت استفاده میکنه و ... کلاً وقتی برنامه ای با سخت افزار کار میکنه این کارهای ناشیانه خیلی خطرناک هستند.
در قرون وسطی! outportb روی یک پورت -I/O سخت افزاری- (اولین پارامتر این تابع) یک بافر میفرستاد و inportb هم از یک پورت، بافری رو برمیگردوند...
این برنامه یک union درست کرده (count) که روی پورت 66 دو بایت c اون رو -که مقداردهی هم نشدن!- میفرسته و روی پورت 67 هم 182 رو میفرسته (که نمیدونم از کجا این اعداد اومدن) و از پورت 97 هم میخونه و هم روش مینویسه و شاید همین کار باعث تولید خروجی صدا بشه ولی من این اعداد رو که نمیشناسم (اونهم دسیمال)!

اگه میخواهید با کارت صوتی کار کنید (16 بیتی)، بهتره یکمی دقیق تر با سخت افزار برخورد کنید، من کد شما رو کامپایل نکردم ولی مثلاً کد زیر برای (DOS) پخش یک فایل wav معمولی از کارت صدا میتونه استفاده بشه :
#include "ALLOC.H"
#include "DOS.H"
#include "CONIO.H"
#include "STDIO.H"

void main()
{
char *name;
printf("Enter the file name...:");
scanf("%s",name);
playwav(name,1.0);
}

void playwav(char wavefile[14],float delaytime);
struct WaveData {
unsigned int SoundLength, Frequency;
char *Sample;
};

struct HeaderType {
long RIFF; //RIFF header
char NI1 [18]; //not important

unsigned int Channels; //channels 1 = mono; 2 = stereo
long Frequency; //sample frequency
char NI2 [6]; //not important
char BitRes; //bit resolution 8/16 bit
char NI3 [12]; //not important
} Header;

struct WaveData Voice; //Pointer to wave file

unsigned int Base; //Sound Blaster base address

char WaveFile [25]; //File name for the wave file to beplayed

/* Checks to see if a Sound Blaster exists at a given address, returns
true if Sound Blaster found, false if not.
*/
int ResetDSP(unsigned int 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);
}
else
//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);
}

/* Plays a part of the memory */

void PlayBack (struct WaveData *Wave)
{
long LinearAddress;
unsigned int Page, OffSet;
unsigned char TimeConstant;
TimeConstant = (65536 - (256000000 / Wave-Frequency)) 8;
WriteDSP(0x40); //DSP-command 40h - Set sample
frequency
WriteDSP(TimeConstant); //Write time constant

//Convert pointer to linear address
LinearAddress = FP_SEG (Wave-Sample);
LinearAddress = (LinearAddress &lt;&lt;Sample);
Page = LinearAddress 16; //Calculate page
OffSet = LinearAddress & 0xFFFF; //Calculate offset in the page
/*
Note - this procedure only works with DMA channel 1
*/
outportb (0x0A, 5); //Mask DMA channel 1
outportb (0x0C, 0); //Clear byte pointer
outportb (0x0B, 0x49); //Set mode
/*
The mode consists of the following:
0x49 = binary 01 00 10 01
| | | |
| | | +- DMA channel 01
| | +---- Read operation (the DSP reads from
memory)
| +------- Single cycle mode
+---------- Block mode
*/

outportb (0x02, OffSet & 0x100); //Write the offset to the DMA
controller
outportb (0x02, OffSet 8);

outportb (0x83, Page); //Write the page to the DMA
controller

outportb (0x03, Wave-SoundLength & 0x100);
outportb (0x03, Wave-SoundLength 8);

outportb (0x0A, 1); //Unmask DMA channel

WriteDSP(0x14); // DSP-command 14h - Single cycle
playback
WriteDSP(Wave-SoundLength & 0xFF);
WriteDSP(Wave-SoundLength 8);
}

/* Loads a wave file into memory.
This procedure expects a _very_ standard wave header.
It doesn't perform much error checking.
*/
int LoadVoice (struct WaveData *Voice, char *FileName)
{
FILE *WAVFile;

//If it can't be opened...
WAVFile = fopen(FileName, "rb");
if (WAVFile == NULL) {
//..display error message
return (0);
}

//Return length of file for sound length minus 48 bytes for .WAV
header
fseek(WAVFile, 0L, SEEK_END);
Voice-SoundLength = ftell (WAVFile) - 48;
fseek(WAVFile, 0L, SEEK_SET);

//Check RIFF header
if (Voice-SoundLength 32000) {
if (Voice-SoundLength 64000) {
Voice-SoundLength = 64000;
}
}
free(Voice-Sample);
Voice-Sample = (char *)malloc(Voice-SoundLength); //Assign memory
if (!Voice-Sample) {

return (0);
}

//Load the sample data
fread(&Header, 46, 1, WAVFile);

//Check RIFF header
if (Header.RIFF != 0x46464952) {
printf ("Not a wave file
");
return (0);
}

//Check channels
if (Header.Channels != 1) {
printf ("Not a mono wave file
");
return (0);
}

//Check bit resolution
if (Header.BitRes != 8) {
printf ("Not an 8-bit wave file
");
return (0);
}

Voice-Frequency = Header.Frequency;

//Load the sample data
fread(Voice-Sample, Voice-SoundLength + 2, 1, WAVFile);
fclose (WAVFile); //Close the file
return (1);
}

void playwav (char wavefile[14], float delaytime )
{
delaytime=1.0;
if (ResetDSP (0x220)) {
//at 220h
printf ("");
} else {
if (ResetDSP (0x240)) {

//at 240h
printf ("");
} else {
//or none at all
printf ("");
return;
}
}

//Load wave file
if (LoadVoice (&Voice, wavefile)) {

//Start playback
PlayBack (&Voice);

delay(delaytime*1000);

//Stops DMA-transfer
WriteDSP (0xD0);
}
}

برای کار با درایورهای 32 بیتی هم که محدودیت هاتون خیلی بیشتر هست و با توجه به نوع سوال پرسیدن تون احتمال میدم حوصله همچین کارهایی رو نداشته باشید! برای کارهای اصولی تر باید از توابع READ_REGISTER_UCHAR و READ_REGISTER_BUFFER_UCHAR و ... یا معادل WRITE همین ها از API های مربوط به WDM استفاده کنید، مثل این نمونه (http://www.codeproject.com/KB/system/WDM_Driver_development.aspx) ...