Motyw: Jak sprawić, by aplikacja Delphi 2 `śpiewała`.
Ta wskazówka pokazuje cztery różne sposoby na śpiewanie aplikacji Delphi 2.0, tj. Pobierz i odtwórz plik dźwiękowy:
1. Aby odtworzyć plik dźwiękowy, użyj bezpośrednio funkcji sndPlaySound ().
2. Przeczytaj plik dźwiękowy do pamięci, a następnie użyj sndPlaySound (), aby go odtworzyć.
3. Użyj sndPlaySound, aby bezpośrednio odtworzyć pliki dźwiękowe znajdujące się w plikach zasobów powiązanych z aplikacją.
4. Przeczytaj plik dźwiękowy znajdujący się w pliku zasobów połączonym z aplikacją w pamięci, a następnie użyj sndPlaySound (), aby go odtworzyć.
Aby zbudować projekt, potrzebujesz:
1. Utwórz plik dźwiękowy o nazwie „hello.wav” w katalogu projektu.
2. Utwórz plik tekstowy o nazwie „snddata.rc” w katalogu projektu.
3. Dodaj następujący wiersz do pliku „snddata.rc”:
.4. W sesji dos przejdź do katalogu aplikacji i skompiluj plik .rc za pomocą kompilatora zasobów Borland (brcc32.exe): wprowadź ścieżkę do brcc32.exe i przekaż „snddata.rc” jako parametr.
Spowoduje to utworzenie pliku snddata.res, który Delphi prowadzi do pliku .exe aplikacji.
wykorzystujeWindows, Wiadomości, SysUtils, Klasy, Grafika, Sterowanie, Formularze, Dialogi, StdCtrls;
typTForm1 \u003d klasa(TForm)
procedura PlaySndFromFileClick (Sender: TObject);
procedura PlaySndFromMemoryClick (Sender: TObject);
procedura PlaySndFromResClick (Sender: TObject);
procedura PlaySndbyLoadResClick (Sender: TObject);
procedura TForm1.PlaySndFromFileClick (Sender: TObject);
sndPlaySound („hello.wav”, SND_FILENAME lub SND_SYNC);
procedura TForm1.PlaySndFromMemoryClick (Sender: TObject);
sndPlaySound (p, SND_MEMORY lub SND_SYNC);
procedura TForm1.PlaySndFromResClick (Sender: TObject);
PlaySound („HELLO”, hInstance, SND_RESOURCE lub SND_SYNC);
procedura TForm1.PlaySndbyLoadResClick (Sender: TObject);
h: \u003d FindResource (hInstance, „HELLO”, „WAVE”);
h: \u003d LoadResource (hInstance, h);
sndPlaySound (p, SND_MEMORY lub snd_sync);
Utwórz nowy plik wav
Motyw: Utwórz nowy plik z rozszerzeniem .wav.
Ten dokument został stworzony na prośbę wielu użytkowników i opisuje dodatkową funkcjonalność komponentu Delphi TMediaPlayer. Nową funkcjonalnością komponentu jest możliwość utworzenia nowego pliku w formacie .wav podczas nagrywania. Procedura SaveMedia tworzy typ rekordu przekazywanego do polecenia MCISend. Istnieje wyjątek, który powoduje zamknięcie nośnika w przypadku wystąpienia błędu podczas otwierania określonego pliku. Aplikacja składa się z dwóch przycisków. Button1 wywołuje kolejno procedury OpenMedia i RecordMedia. Procedura CloseMedia jest wywoływana, gdy aplikacja zgłasza wyjątek. Button2 wywołuje StopMedia, SaveMedia i CloseMedia.
wykorzystujeWindows, Wiadomości, SysUtils, Klasy, Grafika, Sterowanie, Formularze, Dialogi, MPlayer, MMSystem, StdCtrls;
typTForm1 \u003d klasa(TForm)
procedura
procedura Button2Click (Sender: TObject);
procedura
procedura AppException (Sender: TObject; E: Wyjątek);
procedura RecordMedia;
procedura CloseMedia;
varMyError, Flags: Longint;
procedura TForm1.OpenMedia;
MyOpenParms: TMCI_Open_Parms;
Flagi: \u003d mci_Wait lub mci_Open_Element lub mci_Open_Type;
z MyOpenParms zaczynać
lpstrDeviceType: \u003d PChar („WaveAudio”);
MyError: \u003d mciSendCommand (0, mci_Open, Flags, Longint (@MyOpenParms));
jeśli MyError \u003d 0 wtedyFDeviceID: \u003d MyOpenParms.wDeviceID;
procedura TForm1.RecordMedia;
MyRecordParms: TMCI_Record_Parms;
z Myrecordparms zaczynać
dwCallback: \u003d Uchwyt; // TForm1.Handle
MyError: \u003d mciSendCommand (FDeviceID, mci_Record, Flags, Longint (@MyRecordParms));
procedura TForm1.StopMedia;
var
jeśli Fdeviceid<> 0 potem zacznij
MyError: \u003d mciSendCommand (FDeviceID, mci_Stop, Flags, Longint (@MyGenParms));
procedura TForm1.SaveMedia;
typ // nie zaimplementowane w Delphi
PMCI_Save_Parms \u003d ^ TMCI_Save_Parms;
TMCI_Save_Parms \u003d nagrywać
lpstrFileName: PAnsiChar; // nazwa pliku do zapisania
varMySaveParms: TMCI_Save_Parms;
jeśli Fdeviceid<> 0 potem zacznij
// zapisz plik ...
Flagi: \u003d mci_Save_File lub mci_Wait;
z MySaveParms zaczynać
lpstrFileName: \u003d PChar („c: \\ message.wav”);
MyError: \u003d mciSendCommand (FDeviceID, mci_Save, Flags, Longint (@MySaveParms));
procedura TForm1.CloseMedia;
varMyGenParms: TMCI_Generic_Parms;
jeśli Fdeviceid<> 0 potem zacznij
MyGenParms.dwCallback: \u003d Uchwyt; // TForm1.Handle
MyError: \u003d mciSendCommand (FDeviceID, mci_Close, Flags, Longint (@MyGenParms));
jeśli MyError \u003d 0 wtedyFDeviceID: \u003d 0;
procedura
procedura TForm1.Button2Click (Sender: TObject);
procedura
Application.OnException: \u003d AppException;
procedura TForm1.AppException (Sender: TObject; E: Wyjątek);
Jak wdrożyć regulację głośności?
Nomadic radzi:
Tak, wszystko jest proste. Nawet, powiedziałbym, pisz. :-)
INT GetMasterVolumeControlID () (
mxl.cbStruct \u003d sizeof (MIXERLINE);
mxl.dwComponentType \u003d MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
if (:: mixerGetLineInfo ((HMIXEROBJ) ghmx, & mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE)! \u003d MMSYSERR_NOERROR) return 34;
mxlc.cbStruct \u003d sizeof (MIXERLINECONTROLS);
mxlc.dwLineID \u003d mxl.dwLineID;
mxlc.dwControlType \u003d MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cbmxctrl \u003d sizeof (MIXERCONTROL);
if (:: mixerGetLineControls ((HMIXEROBJ) ghmx, & mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE)! \u003d MMSYSERR_NOERROR) return 34;
BOOL SetMasterVolume (DWORD dwVolume) (
MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
mxcd.cbStruct \u003d sizeof (mxcd);
mxcd.dwControlID \u003d MasterVolumeControlID;
mmr \u003d mixerGetControlDetails ((HMIXEROBJ) ghmx & mxcd, 0L);
mmr \u003d mixerSetControlDetails ((HMIXEROBJ) ghmx & mxcd, 0L);
jeśli (MMSYSERR_NOERROR! \u003d mmr) zwraca FALSE;
Przepisanie do Delphi, jak sądzę, na cokolwiek. Trzeba tylko pamiętać, aby dodać używa MMSystem; Głośność poszczególnych kanałów można bardzo łatwo ustawić za pomocą auxSetVolume i tym podobnych.
Jak korzystać z interfejsów API DirectSound i DirectSound3D w moim programie?
Nomadic radzi:
Przykład 1Przedstawiam wam praktyczny przykład użycia DirectSound na Delphi + z kilkoma przydatnymi procedurami. Ten przykład tworzy jeden podstawowy SoundBuffer i 2 statyczne, dodatkowe; ładują 2 pliki WAV. Bufor podstawowy jest tworzony przez procedurę AppCreateWritePrimaryBuffer, a każdy bufor dodatkowy jest tworzony przez AppCreateWritePrimaryBuffer. Ponieważ bufor dodatkowy jest powiązany z plikiem WAV, podczas tworzenia bufora należy określić jego parametry zgodnie z plikiem dźwiękowym, dlatego te cechy (Próbki, Bity, IsStereo) są ustawiane w postaci parametrów procedury. Czas - czas pliku WAV w sekundach (zaokrąglanie w górę). Po naciśnięciu przycisku następuje mieszanie buforów pomocniczych z buforami pierwotnymi AppWriteDataToBuffer umożliwia zapisanie sygnału do bufora PCM. Procedura CopyWAVToBuffer otwiera plik WAV, oddziela nagłówek, odczytuje fragment danych i kopiuje go do bufora (w tym samym czasie najpierw odczytywany jest rozmiar danych, ponieważ w niektórych plikach WAV jest dołączany tekst, a jeśli nie zostanie usunięty, możliwe jest pękanie w głośnikach).
PS. Jeśli będą jakieś pytania, postaram się na nie odpowiedzieć.
wykorzystuje
typTForm1 \u003d klasa(TForm)
procedura FormCreate (Sender: TObject);
procedura
procedura Button1Click (Sender: TObject);
SecondarySoundBuffer: tablica z IDirectSoundBuffer;
procedura
procedura AppCreateWriteSecondaryBuffer ( var
procedura var
procedura CopyWAVToBuffer (nazwa: PChar;
var
procedura TForm1.FormCreate (Sender: TObject);
jeśliDirectSoundCreate ( zero, DirectSound, zero) <> DS_OK następnie podnieś
AppCreateWriteSecondaryBuffer (SecondarySoundBuffer, 22050, 8, False, 10);
AppCreateWriteSecondaryBuffer (SecondarySoundBuffer, 22050, 16, True, 1);
procedura
jeśliPrzypisany (DirectSoundBuffer) wtedy DirectSoundBuffer.Release;
dla i: \u003d 0 do 1 zrobić jeśli Assigned (SecondarySoundBuffer [i]) wtedy SecondarySoundBuffer [i] .Release;
jeśli Przypisany (DirectSound) wtedy DirectSound.Release;
procedura
H: \u003d;
jeśli H \u003d DSERR_BUFFERLOST potem zacznij
jeśli Buffer.Lock (OffSet, SoundBytes, AudioPtr1, AudioBytes1, AudioPtr2, AudioBytes2, 0)<> DS_OK następnie podnieś
inaczej jeśli H.<> DS_OK następnie podnieś Exception.Create („Nie można zablokować bufora dźwięku”);
jeśli AudioPtr2<> zero wtedy zacznij
jeśli <> DS_OK następnie podnieś
procedura
z Bufferdesk zaczynać
jeśli <> DS_OK następnie podnieś
jeśli zero) <> DS_OK następnie podnieś
jeśli <> DS_OK następnie podnieś
jeśli DirectSound.SetCooperativeLevel (uchwyt, DSSCL_NORMAL)<> DS_OK następnie podnieś Exception.Create („Nie można ustawić poziomu współpracy”);
procedura TForm1.AppCreateWriteSecondaryBuffer;
FillChar (BufferDesc, SizeOf (DSBUFFERDESC), 0);
FillChar (PCM, SizeOf (TWaveFormatEx), 0);
z Bufferdesk zaczynać
PCM.wFormatTag: \u003d WAVE_FORMAT_PCM;
jeśli isStereo wtedy PCM.n Kanały: \u003d 2
jeszcze PCM.nChannels: \u003d 1;
PCM.nBlockAlign: \u003d (Bity div 8) * PCM.nKanały;
PCM.nAvgBytesPerSec: \u003d PCM.nSamplesPerSec * PCM.nBlockAlign;
dwSize: \u003d SizeOf (DSBUFFERDESC);
jeśli zero) <> DS_OK następnie podnieś Exception.Create („Utworzenie bufora dźwięku nie powiodło się”);
procedura TForm1.CopyWAVToBuffer;
do Chunk \u003d „data”;
procedura TForm1.Button1Click (Sender: TObject);
CopyWAVToBuffer („1.wav”, SecondarySoundBuffer);
CopyWAVToBuffer („flip.wav”, SecondarySoundBuffer);
jeśli <> DS_OK wtedy
jeśli SecondarySoundBuffer.Play (0, 0, 0)<> DS_OK wtedy ShowMessage („Can” „t play the Sound”);Przykład 2
Przedstawiam państwu kolejny przykład pracy z DirectSound na Delphi. Ten przykład pokazuje, jak pracować z buforem 3D. Tak więc pozostawiłem procedury AppCreateWritePrimaryBuffer, AppWriteDataToBuffer, CopyWAVToBuffer bez zmian (patrz litery wcześniej). Procedura AppCreateWriteSecondary3DBuffer jest kompletnym analogiem procedury AppCreateWriteSecondaryBuffer, z wyjątkiem flagi DSBCAPS_CTRL3D, która wskazuje, że inny bufor zostanie powiązany ze statycznym buforem wtórnym - SecondarySound3DBuffer. Aby go zainicjować, a także ustawić niektóre wartości początkowe (pozycja w przestrzeni, prędkość itp.), Wywoływana jest procedura AppSetSecondary3DBuffer, której parametrami są SecondarySoundBuffer i powiązany SecondarySound3DBuffer. W tej procedurze SecondarySound3DBuffer jest inicjowany przy użyciu metody QueryInterface z odpowiednią flagą. Ponadto tutaj ustawia się także pozycję źródła dźwięku w przestrzeni: SetPosition (Pos, 1 (X), 1 (Y), 0 (Z)).
Zatem w początkowym momencie źródło znajduje się na wysokości 1 m (oś Y jest skierowana pionowo w górę, a oś Z „skierowana jest w stronę ekranu”). Widziane z góry:
Punkt O (właściwie ty) ma współrzędne (0,0), źródło dźwięku A (-25,1). Oczywiście pojęcie „miernika” jest bardzo arbitralne.
Po naciśnięciu przycisku dźwięk „xhe4.wav” jest ładowany do bufora SecondarySoundBuffer. Jest to dźwięk działającego wirnika śmigłowca, jego długość (dźwięk) wynosi dokładnie 3,99 s (a rozmiar bufora dokładnie 4 s). Następnie następuje mieszanie z bufora dodatkowego do podstawowego z flagą DSBPLAY_LOOPING, co pozwala na powtarzanie powtarzanego dźwięku; czas ucha 0,01 praktycznie nie jest rejestrowany i uzyskuje się ciągły dźwięk latającego helikoptera. Następnie uruchamia się licznik czasu (pole INTERWAŁ w Inspektorze obiektów jest ustawione na 1). Oczywiście nie musisz tego robić, to tylko przykład. W procedurze Timer1Timer współrzędna X zmienia się po prostu o 0,1.
W rezultacie otrzymujemy latający helikopter od lewej do prawej. Jednocześnie możesz sprawdzić, czy głośniki są prawidłowo ustawione.
PS. Jeśli masz pytania, postaram się na nie odpowiedzieć.
wykorzystujeWindows, Wiadomości, SysUtils, Klasy, Grafika, Sterowanie, Formularze, Dialogi, DSound, MMSystem, StdCtrls, ExtCtrls;
typTForm1 \u003d klasa(TForm)
procedura FormCreate (Sender: TObject);
procedura FormDestroy (Sender: TObject);
procedura Button1Click (Sender: TObject);
procedura Timer1Timer (Sender: TObject);
DirectSoundBuffer: IDirectSoundBuffer;
SecondarySoundBuffer: IDirectSoundBuffer;
SecondarySound3DBuffer: IDirectSound3DBuffer;
procedura AppCreateWritePrimaryBuffer;
procedura AppCreateWriteSecondary3DBuffer ( var Bufor: IDirectSoundBuffer; SamplesPerSec: Integer; Bity: Word; isStereo: Boolean; Czas: liczba całkowita);
procedura AppSetSecondary3DBuffer ( var Bufor: IDirectSoundBuffer; var _3DBuffer: IDirectSound3DBuffer);
procedura AppWriteDataToBuffer (Buffer: IDirectSoundBuffer; OffSet: DWord; var SoundData SoundBytes: DWord);
procedura CopyWAVToBuffer (nazwa: PChar; var Bufor: IDirectSoundBuffer);
procedura TForm1.FormCreate (Sender: TObject);
jeśliDirectSoundCreate ( zero, DirectSound, zero) <> DS_OK następnie podnieś Exception.Create („Nie udało się utworzyć obiektu IDirectSound”);
AppCreateWriteSecondary3DBuffer (SecondarySoundBuffer, 22050, 8, False, 4);
AppSetSecondary3DBuffer (SecondarySoundBuffer, SecondarySound3DBuffer); Timer1.Enabled: \u003d False;
procedura TForm1.FormDestroy (Sender: TObject);
jeśliPrzypisany (DirectSoundBuffer) wtedy DirectSoundBuffer.Release;
jeśli Przypisany (SecondarySound3DBuffer) wtedy SecondarySound3DBuffer.Release;
jeśli Assigned (SecondarySoundBuffer) wtedy SecondarySoundBuffer.Release;
jeśli Przypisany (DirectSound) wtedy DirectSound.Release;
procedura TForm1.AppCreateWritePrimaryBuffer;
FillChar (BufferDesc, SizeOf (DSBUFFERDESC), 0);
FillChar (PCM, SizeOf (TWaveFormatEx), 0);
z Bufferdesk zaczynać
PCM.wFormatTag: \u003d WAVE_FORMAT_PCM;
PCM.nAvgBytesPerSec: \u003d PCM.nSamplesPerSec * PCM.nBlockAlign;
dwSize: \u003d SizeOf (DSBUFFERDESC);
dwFlags: \u003d DSBCAPS_PRIMARYBUFFER;
jeśli DirectSound.SetCooperativeLevel (uchwyt, DSSCL_WRITEPRIMARY)<> DS_OK następnie podnieś
jeśli DirectSound.CreateSoundBuffer (BufferDesc, DirectSoundBuffer, zero) <> DS_OK następnie podnieś Exception.Create („Utworzenie bufora dźwięku nie powiodło się”);
jeśli DirectSoundBuffer.SetFormat (PCM)<> DS_OK następnie podnieś Exception.Create („Nie można ustawić formatu”);
jeśli DirectSound.SetCooperativeLevel (uchwyt, DSSCL_NORMAL)<> DS_OK następnie podnieś Exception.Create („Nie można ustawić poziomu współpracy”);
procedura TForm1.AppCreateWriteSecondary3DBuffer;
FillChar (BufferDesc, SizeOf (DSBUFFERDESC), 0);
FillChar (PCM, SizeOf (TWaveFormatEx), 0);
z Bufferdesk zaczynać
PCM.wFormatTag: \u003d WAVE_FORMAT_PCM;
jeśli isStereo, a następnie PCM.n Kanały: \u003d 2
jeszcze PCM.nChannels: \u003d 1;
PCM.nSamplesPerSec: \u003d SamplesPerSec;
PCM.nBlockAlign: \u003d (Bity div 8) * PCM.nKanały;
PCM.nAvgBytesPerSec: \u003d PCM.nSamplesPerSec * PCM.nBlockAlign;
dwSize: \u003d SizeOf (DSBUFFERDESC);
dwFlags: \u003d DSBCAPS_STATIC lub DSBCAPS_CTRL3D;
dwBufferBytes: \u003d Czas * PCM.nAvgBytesPerSec;
jeśli DirectSound.CreateSoundBuffer (BufferDesc, Buffer, zero) <> DS_OK następnie podnieś Exception.Create („Utworzenie bufora dźwięku nie powiodło się”);
procedura TForm1.AppWriteDataToBuffer;
AudioPtr1, AudioPtr2: Wskaźnik;
AudioBytes1, AudioBytes2: DWord;
jeśli H \u003d DSERR_BUFFERLOST potem zacznij
jeśli Buffer.Lock (OffSet, SoundBytes, AudioPtr1, AudioBytes1, AudioPtr2, AudioBytes2, 0)<> DS_OK następnie podnieś Exception.Create („Nie można zablokować bufora dźwięku”);
inaczej jeśli H.<> DS_OK następnie podnieś Exception.Create („Nie można zablokować bufora dźwięku”);
Przenieś (Temp ^, AudioPtr1 ^, AudioBytes1);
jeśli AudioPtr2<> zero wtedy zacznij
Inc (liczba całkowita (temperatura), AudioBytes1);
Przenieś (Temp ^, AudioPtr2 ^, AudioBytes2);
jeśli Buffer.UnLock (AudioPtr1, AudioBytes1, AudioPtr2, AudioBytes2)<> DS_OK następnie podnieś Exception.Create („Nie można odblokować bufora dźwięku”);
procedura TForm1.CopyWAVToBuffer;
FName: \u003d TFileStream.Create (nazwa, fmOpenRead);
FName.Seek (Pos, soFromBeginning);
do Chunk \u003d „data”;
FName.Seek (Pos + 3, soFromBeginning);
FName.Read (DataSize, SizeOf (DWord));
AppWriteDataToBuffer (Buffer, 0, Data ^, DataSize);
var Pos: Pojedyncze \u003d -25;
procedura TForm1.AppSetSecondary3DBuffer;
jeśliBuffer.QueryInterface (IID_IDirectSound3DBuffer, _3DBuffer)<> DS_OK następnie podnieś Exception.Create („Nie udało się utworzyć obiektu IDirectSound3D”);
jeśli _3DBuffer.SetPosition (Pos, 1, 1, 0)<> DS_OK następnie podnieś Exception.Create („Nie udało się ustawić pozycji IDirectSound3D”);
procedura TForm1.Button1Click (Sender: TObject);
CopyWAVToBuffer („xhe4.wav”, SecondarySoundBuffer);
jeśli SecondarySoundBuffer.Play (0, 0, DSBPLAY_LOOPING)<> DS_OK wtedy ShowMessage („Can” „t play the Sound”);
procedura TForm1.Timer1Timer (Sender: TObject);
SecondarySound3DBuffer.SetPosition (Pos, 1,1,0);
W tym artykule postaram się rozważyć trzy procedury odtwarzania dźwięku. Zastosowanie tych procedur zamiast komponentu TMediaPlayer znacznie zaoszczędzi zasoby systemowe. Korzystając z tych procedur, możesz rozwiązać dość szeroki zakres zadań. Rozpatrzymy te procedury od najprostszej.
Procedura dźwiękowa
Ta procedura nie ma parametrów. Jej reklama wygląda dość prosto:
Istotą tej procedury jest odtworzenie standardowego sygnału dźwiękowego zainstalowanego w systemie Windows, jeśli istnieje karta dźwiękowa i skonfigurowany jest standardowy dźwięk, jeśli nie, dźwięk będzie odtwarzany przez głośnik komputera w postaci krótkiego kliknięcia. Można go użyć na przykład, gdy użytkownik wprowadzi nieprawidłowe dane lub podczas zamykania formularza:
procedura TForm1.FormClose (Sender: TObject; var Action: TCloseAction);
zacząć
Beep
koniec;
Wymyśliliśmy pierwszą procedurę. Zobaczmy teraz drugi ...
Funkcja MessageBeep
Ta funkcja jest poważniejsza i jest zdefiniowana jako:
funkcja MessageBeep (uType: word): boolean;
Parametr uType określa odtwarzany dźwięk, jako identyfikator klucza rejestru, w którym rejestrowane są dźwięki towarzyszące tym lub innym zdarzeniom systemu Windows. Parametr uType może przyjmować następujące wartości:
- MB_ICONASTERISK - odtwarza dźwięk „Asterisk” (SystemAsterisk)
- MB_ICONEXCLAMATION - odtwarza dźwięk „Exclamation” (SystemExclamation)
- MB_ICONHAND - odtwarza dźwięk „Critical Error” (SystemHand)
- MB_ICONQUESTION - odtwarza dźwięk „Pytanie” (pytanie systemowe)
- MB_OK - odtwarza dźwięk „Standard Sound” (SystemDefault)
Należy zauważyć, że ta funkcja odtwarza dźwięk asynchronicznie, tj. podczas odtwarzania dźwięku aplikacja nadal działa. Po żądaniu dźwięku MessageBeep przenosi kontrolę do funkcji, która go wywołała.
Jeśli odtworzenie określonego dźwięku nie jest możliwe, funkcja spróbuje odtworzyć domyślny zestaw dźwięków systemowych, jeśli nie jest to możliwe, standardowy dźwięk będzie odtwarzany przez głośnik.
I w końcu pozostaje najbardziej interesująca i użyteczna funkcja odtwarzania dźwięku, porozmawiamy o tym teraz.
Funkcja PlaySound
Ta funkcja może odtwarzać dowolne dźwięki fal, a nie tylko dźwięki zdarzeń systemu Windows. Funkcja Windows API, której parametry są opisane w module mmsystem. Dlatego, aby użyć tej funkcji w swoich programach, musisz uwzględnić moduł mmsystem w sekcji zastosowań. Funkcja PlaySound jest zdefiniowana w następujący sposób:
funkcja PlaySound (pszSound: PChar; hmod: HINST; fdwSound: Cardinal): boolean;
Parametr pszSound jest łańcuchem zakończonym zerem (ostatni znak łańcucha ma kod zerowy), określa odtwarzany dźwięk. Parametr hmod jest używany, gdy dźwięk jest pobierany z zasobu, ponieważ nie zrobimy tego, możesz ustawić ten parametr na 0 lub zero.
Ostatni parametr, fdwSound, to zestaw, który określa sposób odtwarzania dźwięku (tryb odtwarzania). Podam najważniejsze wartości tego zestawu do odtwarzania flag o dowolnej fali.
- SND_ASYNC - Dźwięk jest odtwarzany asynchronicznie, a funkcja powraca natychmiast po rozpoczęciu odtwarzania. Aby zatrzymać odtwarzanie, musisz wywołać funkcję PlaySound z parametrem pszSound równym 0.
- SND_LOOP - powtarzanie dźwięku jest ciągle powtarzane; jednocześnie należy ustawić flagę SND_ASYNC.
- SND_NOSTOP - Jeśli określonego dźwięku nie można odtworzyć z powodu zajętych zasobów, funkcja natychmiast zwróci false (i dźwięk nie zostanie odtworzony). Jeśli ta flaga nie zostanie określona, \u200b\u200bfunkcja spróbuje przerwać odtwarzanie innego dźwięku w celu zwolnienia zasobów.
- SND_PURGE - Zatrzymuje odtwarzanie dźwięków spowodowanych w tym zadaniu.
- SND_SYNC - Synchroniczne odtwarzanie dźwięku zdarzenia. Funkcja PlaySound powraca dopiero po zakończeniu odtwarzania.
Ważne: flagi można łączyć z lub.
Dźwięk określony w parametrze pszSound powinien być odpowiedni dla zainstalowanego sterownika urządzenia do odtwarzania plików wave, a także powinien znajdować się w dostępnej pamięci.
Możesz przerwać dźwięk, wykonując instrukcję
PlaySound (0, 0, SND_PURGE);
lub ustawiając nowy dźwięk.
Na przykład, aby wielokrotnie i asynchronicznie odtwarzać niektóre dźwięki wybrane za pomocą OpenDialog, możesz napisać następujący kod:
procedura TForm1.Button1Click (Sender: TObject);
var PCh: PChar;
zacząć
jeśli OpenDialog1.Execute, to
zacząć
StrPCopy (PCh, OpenDialog1.FileName);
PlaySound (Pch, 0, SND_ASYNC lub SND_LOOP);
koniec;
koniec;
Mam nadzieję, że wszystko jest jasne! Następnym razem będzie coś bardziej skomplikowanego i ciekawszego!
Po skonfigurowaniu komponentów należy ustawić rozmiar formularza zgodnie z rozmiarem komponentu Image1, tak aby komponenty MediaPlayer1, SpeedButton5 i SpeedButton6 znajdowały się poza granicą formy. W rezultacie kształt powinien wyglądać tak, jak pokazano na rys. 10.17
Ryc. 10.17 Ostateczna forma „odtwarzacza MP3”
Regulacja głośności
Możesz ustawić żądaną głośność odtwarzania pliku MP3 za pomocą funkcji API waveOutSetVolume. Aby ta funkcja stała się dostępna, należy umieścić łącze do modułu MMSystem w tekście programu (podaj nazwę modułu w dyrektywie uses).
Instrukcja wywołania funkcji wygląda następująco:
r \u003d waveOutSetVolume (identyfikator urządzenia, głośność)
Parametr ID urządzeniaustawia urządzenie odtwarzające (a dokładniej kanał dźwiękowy), którego głośność musi być ustawiona. Podczas regulacji głośności odtwarzania pliku MP3 wartość tego parametru powinna być równa
WAVE_MAPPER (stała WAVE_MAPPER jest zdefiniowana w module MMSystem).
Parametr Głośność (podwójne słowo) ustawia głośność odtwarzania: dolne słowo określa głośność lewego kanału, najwyższe słowo określa głośność prawego kanału. Maksymalna głośność kanału odpowiada wartości szesnastkowej FFFF, minimalna - 0000. Tak więc, aby ustawić maksymalną głośność odtwarzania w obu kanałach, wartość parametru Volume powinna wynosić $ FFFFFFFF (w Delphi prefiks $ jest używany podczas pisania stałych szesnastkowych). Poziom głośności 50% odpowiada stałej wartości 7FFF7FFF.
Należy pamiętać, że funkcja waveOutSetVolume dostosowuje głośność odtwarzania kanał dźwiękowyzamiast ogólnego poziomu dźwięku.
Zmień głośność za pomocą komponentu TrackBar1. Należy zauważyć, że gdy komponent jest ustawiony pionowo, górna pozycja suwaka odpowiada zerowej wartości właściwości Position, a dolna odpowiada wartości określonej przez właściwość Max. Dlatego poziom głośności odpowiadający położeniu silnika oblicza się jako różnicę między prądem a maks
najniższa możliwa wartość właściwości Position (ta wartość ustawia właściwość Max), pomnożona przez $ FFFF.
Bezpośrednia zmiana głośności jest wykonywana przez procedurę przetwarzania zdarzenia Change (Listing 10.14), kontroli głośności (komponent TrackBar1), która występuje w wyniku przesunięcia kursora za pomocą myszy lub klawiszy kursora. Najpierw oblicza wartość głośności dla lewego kanału, a następnie dodaje tę samą wartość przesuniętą o 16 bitów do odebranej wartości (w rezultacie te same i wyższe wartości znajdują się w słowach wysokich i niskich), a tak otrzymana wartość jest przekazywana jako parametr do funkcji
waveOutSetVolume.
Listing 10.14. Obsługa zdarzenia zmiany komponentu TrackBar1
zacząć
volume: \u003d $ FFFF * (TrackBar1.Max - TrackBar1.Position); objętość: \u003d objętość + (objętość shl 16); waveOutSetVolume (WAVE_MAPPER, wolumin);
koniec;
Okno się porusza
Wartość właściwości BorderStyle formularza to bsNone, dlatego tytuł nie jest wyświetlany w oknie programu (patrz rys. 10.5), a zatem na pierwszy rzut oka użytkownik wydaje się być pozbawiony możliwości przesuwania okna po ekranie w zwykły sposób. Niemniej jednak okno programu można nadal przenosić. Aby to zrobić, ustaw wskaźnik myszy na wolny punkt okna (nie zajmowany przez komponenty), naciśnij lewy przycisk myszy i przytrzymaj go, przeciągnij okno do żądanego punktu na ekranie (ta metoda jest bardzo powszechna). Opisana metoda przenoszenia okna jest zapewniona przez procedurę przetwarzania zdarzenia MouseDown w polu komponentu Image1 (lista 10.15). Procedura „oszukuje” system operacyjny, informuje go (wysyłając odpowiedni komunikat), że użytkownik kliknął przycisk myszy w tytule okna, czyli wykonał akcję wymagającą przeniesienia okna.
Listing 10.15. Obsługa zdarzenia MouseDown w polu komponentu Image1
// W takim przypadku użytkownik może przesunąć okno w zwykły sposób
SendMessage (Form1.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0) koniec;
Tekst programu
Pełny tekst programu odtwarzacza MP3 pokazano na Listingu 10.16.
Listing 10.16. Odtwarzacz MP3
(Odtwarzacz MP3 z regulacją głośności.
(c) Kultin N.B., 2003-2010)
jednostka MainForm;
Windows, Wiadomości, SysUtils, Warianty, Klasy, Grafika, Kontrolki, Formularze, Dialogi, StdCtrls, Przyciski, ExtCtrls, MPlayer, ComCtrls, MMSYSTEM, FileCtrl, Menu; // te linki są wstawiane ręcznie
TForm1 \u003d klasa (TForm) MediaPlayer1: TMediaPlayer;
SpeedButton1: TSpeedButton; // poprzednia kompozycjaSpeedButton2: TSpeedButton; // Play / Stop SpeedButton3: TSpeedButton; // następna kompozycjaSpeedButton4: TSpeedButton; // wybierz folder
// niewidoczne przyciski SpeedButton5 i SpeedButton6 zapewniają
// przechowywanie zdjęć Play i Stop
SpeedButton5: TSpeedButton;
SpeedButton6: TSpeedButton;
ListBox1: TListBox; // lista piosenek
Część II Warsztaty programistyczne |
|
Label1: TLabel; // grywalna kompozycja
Label2: TLabel; // czas gry
Image1: TImage; // tło
PopupMenu1: TPopupMenu; // menu kontekstowe
N1: TMenuItem; // „Zamknij”
N2: TMenuItem; // „Minimalizuj”
// regulacja głośności
Panel1: TPanel; // Panel TrackBar1: TTrackBar;
procedura Image1MouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedura N2Click (Sender: TObject); procedura N1Click (Sender: TObject);
procedura FormCreate (Sender: TObject); procedura ListBox1Click (Sender: TObject); procedura SpeedButton2Click (Sender: TObject); procedura SpeedButton1Click (Sender: TObject); procedura SpeedButton3Click (Sender: TObject); procedura TrackBar1Change (Sender: TObject); procedura Timer1Timer (Sender: TObject); procedura SpeedButton4Click (Sender: TObject);
// te deklaracje są wstawiane tutaj ręcznie procedura Odtwórz; // zagraj
procedura PlayList (ścieżka: ciąg); // tworzy listę plików MP3
(Prywatne deklaracje) publiczne
(Oświadczenia publiczne) zakończone;
($ R * .dfm) var
SoundPath: string; // katalog, w którym znajdują się pliki MP3
min, sec: liczba całkowita; // czas gry
tom: LongWord; // głośność odtwarzania:
// najwyższe słowo to właściwy kanał,
// niskie słowo zostało
procedura TForm1.FormCreate (Sender: TObject); zacząć
PlayList („”); // utwórz listę plików MP3
ListBox1.ItemIndex: \u003d 0; Label1.Caption: \u003d ListBox1.Items;
// ustaw poziom głośności
TrackBar1.Position: \u003d 7;
// wysokie słowo zmiennej głośności to właściwy kanał,
// w lewym dolnym rogu
volume: \u003d (TrackBar1.Position - TrackBar1.Max + 1) * $ FFFF; objętość: \u003d objętość + (objętość shl 16); waveOutSetVolume (WAVE_MAPPER, wolumin); // poziom głośności
koniec;
// tworzy listę procedur plików MP3 TForm1.PlayList (Path: string); var
SearchRec: TSearchRec; // Struktura SearchRec zawiera informacje // o pliku, który spełnia warunek wyszukiwania
// utwórz listę plików MP3
jeśli FindFirst (ścieżka + „* .mp3”, faAnyFile, SearchRec) \u003d 0, to zacznij
// Katalog ma plik z rozszerzeniem mp3.
// Dodaj nazwę tego pliku do listy.
ListBox1.Items.Add (SearchRec.Name);
Część II Warsztaty programistyczne |
|
// Jeszcze jakieś pliki MP3?
while (FindNext (SearchRec) \u003d 0) do ListBox1.Items.Add (SearchRec.Name);
koniec; ListBox1.ItemIndex: \u003d 0;
koniec;
// kliknij tytuł pracy
procedura TForm1.ListBox1Click (Sender: TObject); zacząć
jeśli SpeedButton2.Tag \u003d 0, wtedy
// wyświetl nazwę wybranego pliku w polu etykiety Label1
Label1.Caption: \u003d ListBox1.Items else
Form1.Play; // aktywuj proces odtwarzania
koniec;
// kliknij przycisk „Odtwórz”
procedura TForm1.SpeedButton2Click (Sender: TObject); zacząć
// właściwość Tag przechowuje informacje o stanie.
// gracz: 0 - stop; 1 - zagraj
jeśli SpeedButton2.Tag \u003d 0, to zacznij // rozpocznij odtwarzanie
Form1.Play; koniec
// po naciśnięciu przycisku odtwarzania
// następnie ponowne naciśnięcie zatrzymuje odtwarzaniezacząć
SpeedButton2.Tag: \u003d 0; MediaPlayer1.Stop;
SpeedButton2.Glyph: \u003d SpeedButton5.Glyph; Timer1.Enabled: \u003d False; SPeedButton2.Hint: \u003d "Play"; Label2.Caption: \u003d "0:00";
koniec;
koniec;
// przycisk „Poprzedni utwór”
procedura TForm1.SpeedButton1Click (Sender: TObject);
jeśli ListBox1.ItemIndex\u003e 0, to
ListBox1.ItemIndex: \u003d ListBox1.ItemIndex - 1; jeśli SpeedButton2.Tag \u003d 1, to
koniec;
// Przycisk „Następny utwór”
procedura TForm1.SpeedButton3Click (Sender: TObject); zacząć
if ListBox1.ItemIndex< ListBox1.Count then ListBox1.ItemIndex:= ListBox1.ItemIndex + 1;
jeśli SpeedButton2.Tag \u003d 1, to Play;
koniec;
// użytkownik zmienił pozycję procedury regulacji głośności TForm1.TrackBar1Change (Sender: TObject);zacząć
volume: \u003d $ FFFF * (TrackBar1.Max - TrackBar1.Position); objętość: \u003d objętość + (objętość shl 16); waveOutSetVolume (WAVE_MAPPER, wolumin);
koniec;
// odtworzenie utworu, którego nazwa jest podświetlona na liście Procedura ListBox1 TForm1.Play;
Timer1.Enabled: \u003d False; Label1.Caption: \u003d ListBox1.Items; MediaPlayer1.FileName: \u003d SoundPath + ListBox1.Items;
Mediaplayer1.Open; oprócz
na EMCIDeviceError zaczynają się
ShowMessage („Błąd dostępu do pliku” + ListBox1.Items);
wyjście koniec;
koniec;
Część II Warsztaty programistyczne |
|
MediaPlayer1.Play; min: \u003d 0;
sec: \u003d 0; Timer1.Enabled: \u003d True;
SpeedButton2.Hint: \u003d "Stop"; SpeedButton2.Tag: \u003d 1;
koniec;
// sygnał timera
procedura TForm1.Timer1Timer (Sender: TObject); zacząć
// zmienić licznik czasujeśli sec< 59
następnie inc (sec) else rozpocząć
sec: \u003d 0; inc (min);
koniec;
// wyświetlać czas odtwarzania
Label2.Caption: \u003d IntToStr (min) + ":"; jeśli sec< 10
następnie Label2.Caption: \u003d Label2.Caption + „0” + IntToStr (sec) else Label2.Caption: \u003d Label2.Caption + IntToStr (sec);
// jeśli odtwarzanie bieżącego utworu nie zostanie zakończone
if MediaPlayer1.Position< MediaPlayer1.Length then exit;
// odtwarzanie bieżącego utworu jest zakończone
Timer1.Enabled: \u003d False; // zatrzymać stoperMediaPlayer1.Stop; // zatrzymaj gracza
if ListBox1.ItemIndex< ListBox1.Count // lista nie jest wyczerpanapotem zacznij
ListBox1.ItemIndex: \u003d ListBox1.ItemIndex + 1; Graj // aktywuj odtwarzaniePlik końcowy MP3
koniec;
// Kliknij przycisk „Folder”.
// Wybierz folder, w którym znajdują się pliki MP3 TForm1.SpeedButton4Click (Sender: TObject);var
Root: string; // katalog główny pwRoot: PWideChar;
Dir: string; zacząć
Root: \u003d ""; // katalog główny - folder pulpitu
GetMem (pwRoot, (Length (Root) +1) * 2);
pwRoot: \u003d StringToWideChar (Root, pwRoot, MAX_PATH * 2);
jeśli nie SelectDirectory („Wybierz folder, w którym znajdują się pliki MP3”, pwRoot, Dir)
następnie Dir: \u003d ""
else Dir: \u003d Dir + "\\";
// wybrany jest katalog, w którym znajdują się pliki MP3
SoundPath: \u003d Dir; PlayList (SoundPath);
koniec;
// kliknij myszą w polu komponentu Image1
procedura TForm1.Image1MouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
// Nie ma tytułu okna. Oszukiwać w systemie Windows. Niech OC myśli
// że przycisk jest wciśnięty i przytrzymany w tytule okna.
// W takim przypadku użytkownik może przesunąć okno w zwykły sposób.
SendMessage (Form1.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0)
koniec;
// wybierz polecenie „Zamknij” w procedurze menu kontekstowego TForm1.N1Click (Sender: TObject);zacząć
Form1.Close; koniec;
koniec