dźwięki z głośnika komputerowego - duży problem z napisaniem

0

mam do napisania program :

Muzyka z klawiatury: aplikacja, w której klawiszom przyporządkowane są dźwięki z całej oktawy,
możliwość podwyższenia i obniżenia oktawy, regulacja długości dźwięku i pauz.

ale całkowicie nie mam pojęcia jak to zrobić - może ktoś posiada gotowy kod albo jakies cenne rady?
z góry dziękuje
Pozdrawiam:)

0

generalnie obsluga glosnika komputerowego powinna byc zaimplementowana w jakiejs niskopoziomowej bibliotece w c/c++ moze to byc np dos.h ,ktora jak nazwa wskazuje jest zbiorem bibliotek pod dos-a wiec raczej nie znajdziesz jej w windosowskich kompilatorach. Mozesz sprobowac uzyc TC lub TCC ,i poszukac w dos.h funkcji do obslugi glosnika , to tyle jezeli chodzi o domysly;]

Jezeli umiesz pisac w assemblerze to bedize to latwe w miare. jeszcze latwiejsze bedzie pisanie programu w cpp z wstawkami w assemblerze. Robilem cos takiego ale szczerze sie przyznam ,ze nie pamietam dokladnie a plik zrodlowy usunalem tydzien temu :/ . Chodzi mniej wiecej o wyslanie na port glosnika instukcja out slowa sterujacego z oznaczajaca odpowiednia wysokosc dzwieku.
Znalazlem cos takieg:

glosnik:
;;wlaczam glosnik
in al,61h
or al,3
out 61h,al
;;ustawiam czestotliwosc
mov bx,440h ; Standardowe "A", 440 Hz
mov dx,12h ; górna część "1234dd"
mov ax,34ddh ; dolna część "1234dd"
div bx ; ax = wartość do wysłania
push ax
mov al,0b6h
out 43h,al
pop ax
out 42h,al
mov al,ah
out 42,al
;;;czekaj
mov cx,0fh
mov dx,4240h
mov ah,86h
int 15h ; pauza o długości CX:DX mikrosekund
;;;koniec
in al,61h
and al,not 3 ; zerujemy bity 0 i 1
out 61h,al
retp

Tu masz w komentarzach opisane jak ustawiac zmienne.
zamykasz to w funkcji w bloku asm{} i dla kazdego klawicza klawiatury wywolujesz z inna czestotliwoscia.

0

Eeem, tzn. jak chcesz PC Speakerem, to może zamiast tego asm daj po prostu:

#include <windows.h>
// ...
Beep(1000,200);

A jak coś konstruktywniejszego, to może użyć MIDI?
Sporo jest do tego bibliotek. Ja kiedyś używałem Allegro, jest w nim też MIDI:
http://alleg.sourceforge.net/stabledocs/en/alleg027.html
albo biblioteki SDL razem z SDL_Mixer:
http://www.libsdl.org/projects/SDL_mixer/
Jest też typowo dźwiękowy Bass, http://www.un4seen.com/
na google możesz pogrzebać za czymś tylko i wyłącznie dla midi specjalnie.

0

Apropos MIDI, bardzo prosty przykład:

#include <dinput.h>
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "dxguid.lib")

char keys[] = {DIK_Z,DIK_S,DIK_X,DIK_D,DIK_C,DIK_V,DIK_G,DIK_B,DIK_H,DIK_N,DIK_J,DIK_M,DIK_COMMA,
	DIK_Q,DIK_2,DIK_W,DIK_3,DIK_E,DIK_R,DIK_5,DIK_T,DIK_6,DIK_Y,DIK_7,DIK_U,DIK_I};

int main()
{
	HMIDIOUT midiOut;
	midiOutOpen(&midiOut, 0xFFFFFFFF, 0, 0, CALLBACK_NULL);
	//midiOutSetVolume(midiOut, 0xFFFFFFFF);
	midiOutShortMsg(midiOut, 0x007800C0 | (/*instrument*/0x10 << 8));

	IDirectInput *di;
	IDirectInputDevice *keyboard;
	DIPROPDWORD dpd;
	dpd.diph.dwSize = sizeof(dpd);
	dpd.diph.dwHeaderSize = sizeof(dpd.diph);
	dpd.diph.dwObj = 0;
	dpd.diph.dwHow = DIPH_DEVICE;
	dpd.dwData     = 32;

	DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, 0);
	di->CreateDevice(GUID_SysKeyboard, &keyboard, 0);
	keyboard->SetDataFormat(&c_dfDIKeyboard);
	keyboard->SetCooperativeLevel(GetForegroundWindow(), DISCL_NONEXCLUSIVE|DISCL_FOREGROUND);
	keyboard->SetProperty(DIPROP_BUFFERSIZE, &dpd.diph);
	keyboard->Acquire();

	BOOL run = true;
	while (run)
	{
		Sleep(10);
		DIDEVICEOBJECTDATA ddd;
		DWORD dwInOut = 1;

		while (run && !keyboard->GetDeviceData(sizeof(ddd), &ddd, &dwInOut, 0) && (dwInOut==1))
		{
			if (ddd.dwOfs == DIK_ESCAPE) {
				run = false;
				break;
			}
			for (int tone=0; tone < sizeof(keys); tone++)
			{
				if (ddd.dwOfs == keys[tone])
				{
					tone = (tone + 0x3C - (tone>12) ) << 8; // (tone>12) mamy dwa te same tony dla ,q
					midiOutShortMsg(midiOut, tone | ((ddd.dwData & 0x80) ? 0x00400090 :  0x00000090));
					break;
				}
			}
		}
	}
	keyboard->Release();
	di->Release();
	midiOutClose(midiOut);
	return 0;
}

Zamiast prymitywnego Sleep (pooling) można stworzyć drugie device i kazać mu blokować wątek póki stan klawiatury się nie zmieni:
Niestety, połączenie buforowania i event-notification w jednym device - działa do wciśnięcia pierwszego klawisza, dlatego potrzebne są dwa 'device' gdzie pierwsze buforuje klawisze, a drugie czeka na dane z klawiatury.
GetForegroundWindow() - wstawiłem dla konsolowego programu, ale równie dobrze działa z hwnd=0

	IDirectInputDevice *keybwait;
	di->CreateDevice(GUID_SysKeyboard, &keybwait, 0);
	keybwait->SetDataFormat(&c_dfDIKeyboard);
	keyboard->SetCooperativeLevel(GetForegroundWindow(), DISCL_NONEXCLUSIVE|DISCL_FOREGROUND);
	HANDLE hEvent = CreateEvent(0,0,0,0);
	keybwait->SetEventNotification(hEvent);
	keybwait->Acquire();

	BOOL run = true;
	while (run && !WaitForSingleObject(hEvent, INFINITE))
	{
		// bez Sleep
	}
	keybwait->SetEventNotification(0);
	CloseHandle(hEvent);
	keybwait->Release();

1 użytkowników online, w tym zalogowanych: 0, gości: 1