









(Artikel ini pertama kali terbit di majalah PC Media edisi 08/2007)
Setelah cukup banyak berkutat dengan pemrograman grafik 3D dengan Direct3D di artikel-artikel sebelumnya, agar tidak bosan, saya ingin mengajak Anda menjelajahi topik pemrograman lain yang tidak kalah menarik, yakni pemrograman suara menggunakan komponen DirectX yang lain, DirectX Audio.
Yang ingin saya diskusikan bersama Anda kali ini adalah dasar-dasar mengenai DirectX Audio meliputi: arsitektur DirectX Audio, istilah-istilah yang sering digunakan dan tentu saja bagian yang paling menarik adalah bagaimana menggunakan DirectX Audio untuk memainkan file audio.
Windows telah lama memiliki fitur multimedia melalui Multimedia Control Interface (MCI), Wave API dan MIDI API. Untuk aplikasi-aplikasi sederhana, MCI sudah cukup memadai untuk digunakan untuk memainkan file WAV atau MIDI.
Namun jika Anda bermaksud mengembangkan aplikasi sound recording kelas berat seperti produk milik CakeWalk atau game dengan kualitas suara yang ok, MCI tidak cocok.
DirectX Audio disediakan oleh Microsoft untuk pengembangan aplikasi audio berkinerja tinggi pada platform Windows. Dengan DirectX Audio, Anda dapat melakukan beberapa hal berikut dengan mudah:
DirectX Audio terdiri atas dua komponen penyusun yakni DirectSound dan DirectMusic. DirectSound, yang diciptakan lebih dulu, ditujukan untuk akses hardware audio yang efisien dan cepat. DirectSound menyediakan mekanisme low-level untuk mengatur hardware audio secara langsung. DirectMusic diciptakan beberapa waktu kemudian, untuk menyediakan pemrograman low-level untuk perangkat MIDI yang disebut DirectMusic Core dan pemrograman level tinggi untuk proses loading dan memainkan (playback) media musik, disebut DirectMusic Performance.
Pada DirectX versi 7, DirectMusic dan DirectSound adalah komponen yang berdiri sendiri (lihat Gambar 1). MIDI dan musik berbasis style diload oleh DirectMusic Performance dan selanjutnya dikirim ke DirectMusic Core yang menangani langsung device MIDI dan synthesizer. Suara dalam bentuk file wave di-load ke memori dan disiapkan oleh aplikasi dan selanjutnya diberikan ke DirectSound yang menangani hardware wave.
Gambar 1. Arsitektur DirectMusic dan DirectSound pada DirectX versi 7 ke bawah.
Setelah rilis DirectMusic, para pengembang aplikasi lebih menyukai DirectMusic Performance untuk menghandle proses loading dan memainkan file musik. Pada DirectX 8, arsitektur DirectMusic dan DirectSound disatukan sehingga DirectMusic Performance digunakan untuk proses loading dan memainkan MIDI dan suara berformat wave. Penyatuan DirectMusic dan DirectSound ini disebut DirectX Audio (Gambar 2). Arsitektur ini tidak berubah pada DirectX 9.
Gambar 2. Arsitektur DirectMusic dan DirectSound pada DirectX 8 dan 9.
Pada DirectX 8, Microsoft menambahkan fungsionalitas pada Performance sehingga dapat membaca file wave dan memainkan suara berformat wave yang tersimpan dalam segment. Perubahan signifikan pada arsitektur ini adalah diperkenalkannya konsep audiopath yang memisahkan DirectMusic Performance dengan DirectMusic Core. Sebuah audiopath adalah audio channel virtual yang mengontrol aliran data suara. DirectMusic Performance menangani satu atau lebih audiopath
Performance adalah jantung DirectX Audio. Performance melakukan inisialisasi audio, mengatur penjadwalan segment-segment, menciptakan dan memetakan audiopath ke segment serta mengontrol proses playback suara.
Loader berfungsi untuk proses file Input/Output juga membaca data audio dari memori atau resource. Penggunaan loader menyederhanakan tugas programmer untuk membaca data audio.
Segment mewakili segala macam audio yang dapat dimainkan. Dapat berupa file MIDI atau wave atau file DirectMusic Segment (format default DirectMusic, berekstensi SGT). Anda dapat membuat lebih dari satu segment dalam sebuah aplikasi. Anda bahkan bisa memainkan beberapa segment secara bersamaan.
AudioPath adalah objek DirectMusic yang bertugas mengatur rute yang harus diambil oleh instrument musik atau efek suara. Tiap segement yang dimainkan melalui sebuah audiopath. Aplikasi dapat memiliki lebih dari satu audiopath.
DirectMusic tidak menyediakan fungsi pembantu untuk menciptakan instance performance dan loader. Anda harus menggunakan fungsi CoCreateInstance() untuk menciptakan instance performance dan loader (lihat Listing 1)
CoCreateInstance(
CLSID_DirectMusicPerformance,
nil,
CLSCTX_INPROC,
IID_IDirectMusicPerformance8,
FPerformance);
CoCreateInstance(
CLSID_DirectMusicLoader,
nil,
CLSCTX_INPROC,
IID_IDirectMusicLoader8,
FLoader);
Setelah pemanggilan kode pada Listing 1, jika sukses, FPerformance akan diisi dengan pointer ke instance interface IDirectMusicPerformance8, sedangkan FLoader akan diisi alamat instance interface IDirectMusicLoader8.
Sebelum fungsi CoCreateInstance() ini dipanggil, Anda harus melakukan inisialisasi COM, dengan memanggil CoInitialize() atau CoInitializeEx() (lihat Listing 2). Setelah selesai dengan COM, sebaiknya Anda panggil CoUnitialize(). Di Delphi, fungsi-fungsi COM dideklarasi di unit ActiveX.pas.
unit ..; interface ... implementation uses ...,ActiveX,..; ... initialization CoInitialize(nil); finalization CoUninitialize; end.
Saya pribadi lebih suka memanggil fungsi inisialisasi COM dibagian inisialisasi unit sehingga kode insialisasi COM otomatis akan dipanggil tiap kali unit direferensi.
Setelah selesai inisialisasi COM dan menciptakan performance, kita perlu memanggil InitAudio milik IDirectMusicPerformance8 untuk melakukan inisialisasi audio (Listing 3). Fungsi InitAudio hanya perlu dipanggil sekali saja.
function InitAudio (ppDirectMusic: PIDirectMusic;
ppDirectSound: PIDirectSound;
hWnd: hWnd;
dwDefaultPathType,
dwPChannelCount,
dwFlags: DWORD;
pParams: PDMUS_AudioParams) : HResult; stdcall;
Contoh pemanggilan InitAudio adalah seperti pada Listing 4:
FPerformance.InitAudio(nil,
nil,
WindowHandle,
DMUS_APATH_SHARED_STEREOPLUSREVERB,
64,
DMUS_AUDIOF_ALL,
nil);
Ok, mari kita bahas satu persatu parameter fungsi InitAudio ini. Parameter ppDirectMusic dan ppDirectSound masing-masing adalah instance DirectMusic dan DirectSound. Jika Anda ingin instance DirectMusic atau DirectSound diciptakan otomatis isi saja dengan nil. hWnd adalah handle window yang digunakan untuk menciptakan interface IDirectSound. Jika ppDirectSound berisi instance DirectSound yang valid, hWnd diabaikan. Parameter dwDefaultPathType berisi tipe audiopath yang diinginkan seperti yang tercantum di Tabel 1. Jika Anda tidak membutuhkan audiopath default, bisa diisi dengan nol.
| Nilai | Deskripsi |
|---|---|
| DMUS_APATH_DYNAMIC_3D | Audiopath untuk suara 3D. |
| DMUS_APATH_DYNAMIC_MONO | Mono |
| DMUS_APATH_DYNAMIC_STEREO | Audiopath stereo. |
| DMUS_APATH_SHARED_STEREOPLUSREVERB | Stereo dan reverb. |
dwPChannelCount adalah jumlah performance channel yang diinginkan. Tiap channel memiliki setting volume dan balance sendiri-sendiri. dwFlags menentukan fitur yang Anda inginkan. Flag yang dapat Anda gunakan tercantum pada Tabel 2. Sebenarnya ada beberapa flag lain namun flag-flag tersebut belum diimplementasikan.
| Flag | Deskripsi |
|---|---|
| DMUS_AUDIOF_3D | 3D buffer. |
| DMUS_AUDIOF_ALL | Semua fitur |
| DMUS_AUDIOF_BUFFERS | Multiple buffer |
| DMUS_AUDIOF_STREAMING | Mendukung streaming waveform |
pParams berisi alamat ke struktur data bertipe D3DMUS_AUDIOPARAMS. Jika diisi dengan nil, maka parameter default akan digunakan. Agar sesuai dengan konvensi penamaan tipe di Delphi, tipe data ini diberi nama TDMus_AudioParams. Record ini memiliki field dwSize, ukuran data. Harus diisi dengan sizeof(TDMus_AudioParams). fInitNow, bertipe Boolean. Jika diisi true, synthesizer akan diciptakan saat ini juga. dwValidData, bertipe Dword berisi flag yang menentukan data apa yang valid. Flag yang dapat digunakan adalah seperti Tabel 3.
| Flag | Deskripsi |
|---|---|
| DMUS_AUDIOPARAMS_FEATURES | Field dwFeatures berisi data yang valid. |
| DMUS_AUDIOPARAMS_VOICES | Field dwVoices berisi data yang valid. |
| DMUS_AUDIOPARAMS_SAMPLERATE | Field dwSampleRate berisi data yang valid. |
| DMUS_AUDIOPARAMS_DEFAULTSYNTH | Field clsidDefaultSynth berisi data valid. Jika flag ini tidak diset, Microsoft software synthesizer yang akan digunakan. |
Untuk membaca file MIDI atau WAV atau file segment (SGT), Anda menggunakan objek loader dengan fungsi LoadObjectFromFile() (Listing 5).
function LoadObjectFromFile(const rguidClassID: TGUID;
const iidInterfaceID: TGUID;
pwzFilePath: PWideChar;
out ppObject): HResult; stdcall;
rquidClassID adalah class ID objek yang kita ingin load. Untuk membaca file audio ke segment kita menggunakan CLSID_DirectMusicSegment.
iidInterfaceID adalah pengenal interface bisa kita isi dengan IID_IDirectMusicSegment8 untuk menciptakan segment bertipe IDirectMusicSegment8. Dengan Delphi, Anda bisa langsung menggunakan nama interface menggantikan pengenal interface. Jadi menggantikan IID_IDirectMusicSegment8 dengan IDirectMusicSegment8 boleh saja dilakukan.
pwzFilePath adalah nama file yang hendak kita baca. Nama ini harus dalam format widestring (2 byte per character). Jika Anda menggunakan ANSI string, pastikan terlebih dahulu mengkonversi string ke tipe widestring. Setelah nama file tersebut bertipe widestring, lakukan typecast ke PWidechar.
ppObject adalah variable yang akan menampung alamat objek yang diciptakan. Untuk kasus kita, objeknya adalah instance IDirectMusicSegment8. Listing 6 berisi contoh bagaimana membaca file WAV ke segment bernama FSound1.
procedure LoadAudioFile;
var afilename:widestring;
apath:string;
begin
apath:=ExtractFilePath(
application.ExeName)+'sound';
afilename:=apath+'explosion.wav';
FLoader.LoadObjectFromFile(
CLSID_DirectMusicSegment,
IID_IDirectMusicSegment8,
PWideChar(afilename),
FSound1);
end;
LoadObjectFromFile sesuai namanya hanya mampu membaca data dari file. Lalu bagaimana bila data tersebut sudah ada, misalnya, di memori. Untuk kasus ini, Anda membutuhkan GetObject() (Listing 7).
function GetObject (const pDesc: TDMus_ObjectDesc;
const riid : TGUID;
out ppv) : HResult; stdcall;
pDesc adalah deskripsi objek yang hendak di-load. Kita akan membasa tipe TDMus_ObjectDesc segera. riid adalah pengenal interface. ppv berisi variable yang akan menampung pointer instance objek.
Tipe data ini mendeskripsikan bagaimana objek yang akan dibaca, terdiri atas field-field berikut:
| Flag | Deskripsi |
|---|---|
| DMUS_OBJ_CATEGORY | Field wszCategory mengandung data valid. |
| DMUS_OBJ_CLASS | guidClass berisi data valid. |
| DMUS_OBJ_OBJECT | quidObject berisi data valid. |
| DMUS_OBJ_DATE | ftDate berisi data valid. |
| DMUS_OBJ_VERSION | vVersion berisi data valid. |
| DMUS_OBJ_NAME | wszName berisi data valid. |
| DMUS_OBJ_FILENAME | wszFilename berisi data valid. |
| DMUS_OBJ_FULLPATH | wszFilename berisi data valid dan berupa nama file lengkap dengan path. |
| DMUS_OBJ_MEMORY | llMemLength dan pbMemData berisi data valid. |
| DMUS_OBJ_STREAM | pStream berisi data valid. |
Contoh bagaimana membaca data audio yang ada dalam stream bisa Anda pelajari di Listing 8. Saya biasanya menginisialisasi struktur ini dengan nol sebelum mengisi field-field menggunakan ZeroMemory().
Untuk membaca data yang ada di memori ke segment, Anda membutuhkan alamat buffer berisi data dan ukuran buffer tersebut. Anda juga membutuhkan field guidClass untuk memberitahukan DirectMusic agar menciptakan instance segment. Oleh karena itu Anda paling tidak harus menggunakan kombinasi flag DMUS_OBJ_CLASS dan DMUS_OBJ_MEMORY.
procedure LoadFromStream(Stream: TStream);
var objdesc:TDMus_ObjectDesc;
begin
if FInternalStream=nil then
FInternalStream:=TMemoryStream.Create;
FInternalStream.CopyFrom(Stream,0);
ZeroMemory(@objDesc,
sizeof(TDMus_ObjectDesc));
objdesc.dwSize:=sizeof(TDMus_ObjectDesc);
objdesc.dwValidData:=DMUS_OBJ_CLASS or
DMUS_OBJ_MEMORY;
objdesc.guidClass:=CLSID_DirectMusicSegment;
objdesc.llMemLength:=FInternalStream.Size;
objdesc.pbMemData:=FInternalStream.Memory;
FLoader.GetObject(objdesc,
IID_IDirectMusicSegment8,
FSegment);
end;
Loader melakukan cache data yang ada di buffer. Buffer yang berisi data tidak boleh dibebaskan sampai loader dibebaskan. Hal ini disebabkan karena loader mungkin membutuhkan data yang ada di buffer tersebut sewaktu-waktu akibat mekanisme cache.
Jika Anda menggunakan DMUS_OBJ_FILENAME atau DMUS_OBJ_FULLPATH, GetObject menjadi mirip LoadObjectFromFile().
Sebelum segment dapat dimainkan, segment perlu didownload ke performance atau audiopath. Proses download, memindahkan data-data instrument dan waveform yang dipakai oleh segment ke performance ke performance.nkan, segment perlua Listing 7. belajar dasarnya.. Untuk mendownload, kita memanggil fungsi Download() milik interface IDirectMusicSegment8 (Listing 9).
function Download (pAudioPath: IUnknown) : HResult; stdcall;
Contoh kode pada Listing 10 mendownload segment bernama FSound1 ke performance.
FSound1.Download(FPerformance);
Untuk memainkan suara yang tersimpan dalam segment, tersedia dua fungsi PlaySegment() dan PlaySegmentEx() (lihat Listing 11). Fungsi pertama tersedia pada interface IDirectMusicPerformance dan IDirectMusicPerformance8 sedangkan fungsi terakhir hanya tersedia pada interface IDirectMusicPerformance8. PlaySegmentEx adalah perluasan fungsi PlaySegment().
function PlaySegment (pSegment: IDirectMusicSegment;
dwFlags: DWORD;
i64StartTime: LongLong;
ppSegmentState: PIDirectMusicSegmentState) : HResult; stdcall;
function PlaySegmentEx (pSource: IUnknown;
pwzSegmentName: PWChar;
pTransition: IUnknown;
dwFlags: DWORD;
i64StartTime: int64;
out ppSegmentState: IDirectMusicSegmentState;
pFrom, pAudioPath: IUnknown) : HResult; stdcall;
pSegment dan pSource adalah objek segment yang akan dimainkan. pwzSegmentName adalah nama segment. Untuk saat ini belum digunakan, jadi harus diisi nil. dwFlags berisi flags yang mengatur bagaimana segment dimainkan. Beberapa flag yang dapat Anda pergunakan tercantum pada Tabel 5. Flag yang tersedia cukup banyak namun menurut saya tidak terlalu relevan karena kita baru belajar dasarnya.
| Flag | Deskripsi |
|---|---|
| DMUS_SEGF_REFTIME | Waktu menggunakan satuan waktu referensi |
| DMUS_SEGF_SECONDARY | Segment sekunder |
| DMUS_SEGF_QUEUE | Segment dimainkan setelah segment utama selesai. Jika menggunakan segment sekunder, maka segement dimainkan setelah segment yang ada pada pFrom. |
| DMUS_SEGF_CONTROL | Segment dimainkan sebagai segment control. |
i64StartTime adalah posisi dimana suara mulai dimainkan. ppSegmentState adalah interface yang berisi status segment yang sedang dimainkan. pFrom berisi segment yang dihentikan ketika segment yang ada di pSource dimainkan, bisa diisi dengan nil. pAudioPath berisi audiopath yang digunakan untuk memainkan segment. Jika diisi nil, audiopath default digunakan.
Contoh kode pada Listing 12 memainkan segment FSound1 dari awal segment menggunakan audiopath default. Status segment disimpan di variable state.
FPerformance.PlaySegmentEx(FSound1,
nil,nil,
0,0,
state,
nil,nil);
Kode pada Listing 13 menghasilkan output yang sama dengan kode pada Listing 12.
FPerformance.PlaySegment(FSound1,
0,0,nil);
Anda bisa mencoba demo DM1.pr dan DM2.dpr yang ada di CD/DVD.
Jika Anda, coba demo DM1.dpr atau DM2.dpr, tiap kali Anda menekan sebuah tombol, segment suara yang sedang dimainkan akan dihentikan. Anda tidak dapat memainkan dua atau lebih segment bersamaan dengan cara di atas. Teknik tersebut hanya cocok untuk aplikasi sound player, di mana musik dimainkan satu per satu.
Dalam aplikasi game, beberapa suara dapat dimainkan bersama sekaligus. Dalam game perang misalnya, suara dentuman meriam, suara senapan dan suara tentara terluka harus dapat dimainkan bersama-sama untuk memberi ilusi perang sesungguhnya.
Untuk dapat memainkan beberapa segment bersamaan, Anda membutuhkan audiopath untuk masing-masing segment. Di demo DM1.dpr dan DM2.dpr, kita hanya menggunakan satu audiopath, yakni audiopath default.
Untuk menciptakan audiopath, Anda dapat menggunakan CreateStandardAudioPath() milik interface IDirectMusicPerformance8 (Listing 14).
function CreateStandardAudioPath (dwType,
dwPChannelCount: DWORD;
fActivate: BOOL;
out ppNewPath: IDirectMusicAudioPath) : HResult; stdcall;
dwType diisi dengan tipe audiopath. Lihat Tabel 1 untuk flag yang tersedia. dwPChannelCount, Anda isi dengan jumlah performance channel yang Anda inginkan. fActivate kita set dengan true untuk mengaktifkan audiopath. Jika Anda set false, Anda dapat mengaktifkannya lain waktu menggunakan fungsi Activate() milik interface IDirectMusicAudioPath8. ppNewPath akan diisi dengan pointer ke instance audiopath. Contoh kode dapat Anda pelajari di Listing 15.
FPerformance.CreateStandardAudioPath(
DMUS_APATH_SHARED_STEREOPLUSREVERB,
64,true,
FAudioPath1);
Selanjutnya audiopath yang hendak digunakan digunakan ketika memanggil PlaySegmentEx(). Tidak cukup dengan itu, Anda juga harus memainkannya menggunakan segment sekunder yakni dengan flag DMUS_SEGF_SECONDARY (Listing 16). Tanpa flag ini, segment akan dimainkan sebagai segment primer. Hanya ada satu segment primer yang dapat dimainkan pada satu saat. Oleh karena itu, segment primer baru akan menggantikan segment primer yang sedang dimainkan.
FPerformance.PlaySegmentEx(FSound1,
nil,nil,
DMUS_SEGF_SECONDARY,
0,
state,
nil,
FAudioPath1);
Silakan Anda coba demo DM3.dpr. Jika Anda tekan tombol meriam, senapan dan bom berulang-ulang, Anda seolah-olah berada dalam suasana perang.
Ada kalanya Anda ingin memainkan musik sebagai latar secara berulang-ulang. Untuk mengatur berapa banyak sebuah segment dimainkan, Anda mengaturnya dengan menggunakan fungsi SetRepeats milik interface IDirectMusicSegment8. Parameter fungsi ini adalah jumlah pengulangan yang Anda inginkan. Jika diisi dengan 0, segment akan dimainkan sekali tanpa pengulangan. Jika diisi dengan konstanta DMUS_SEG_REPEAT_INFINITE, segment akan dimainkan berulang-ulang sampai dihentikan secara ekplisit. Contoh pemanggilan SetRepeats() bisa Anda pelajari di Listing 17.
//segment diulang sekali FSegment1.SetRepeats(1); //looping terus menerus FSegment1.SetRepeats(DMUS_SEG_REPEAT_INFINITE);
Untuk mengetahui apakah suatu segment sedang dimainkan, Anda dapat menggunakan fungsi isPlaying() milik interface IDirectMusicPerformance8 (Listing18).
function IsPlaying (pSegment: IDirectMusicSegment;
pSegState: IDirectMusicSegmentState) : HResult; stdcall;
Kita dapat mengecek menggunakan segment atau segment state. Jika pSegment berisi nil, yang digunakan adalah pSegState atau sebaliknya pSegState nil maka pSegment yang digunakan.
Jika segment sedang dimainkan, nilai kembali fungsi ini adalah S_OK atau S_FALSE bila sebaliknya.
Segment yang sedang dimainkan dapat dihentikan dengan menggunakan Stop() atau StopEx() (Listing 19). Kedua fungsi adalah fungsi objek performance. Fungsi StopEx adalah perluasan Stop() dan tersedia pada interface IDirectMusicPerformance8.
function Stop (pSegment: IDirectMusicSegment;
pSegmentState: IDirectMusicSegmentState;
mtTime: TMusic_Time;
dwFlags: DWORD) : HResult; stdcall;
function StopEx (pObjectToStop: IUnknown;
i64StopTime: int64;
dwFlags: DWORD) : HResult; stdcall;
pSegment adalah segment yang hendak dihentikan Jika diisi nil, semua segment yang sedang dimainkan akan dihentikanada padahenti. Jika diisi nol, segment dihentikan seketika.idownload.ggil Unload() untuk mengunl. pObjectToStop adalah segment atau segment state atau audiopath yang hendak dihentikan. mtTime dan i64StopTime adalah waktu berhenti. Jika diisi nol, segment dihentikan seketika. dwFlags adalah flag yang mempengaruhi bagaimana segment dihentikan bisa diisi nol atau flag yang ada pada Tabel 5. Contoh bagaimana menghentikan segment dapat Anda lihat di Listing 20.
//menghentikan semua segment FPerformance.Stop(nil,nil,0,0); //Menghentikan segment FSound1 FPerformance.StopEx(FSound1,0,0);
DirectX Audio tidak menyediakan fungsi khusus untuk melakukan pause, namun Anda bisa menghasilkan aksi yang mirip dengan pause dengan menggunakan StopEx() dan PlaySegmentEx().
Sebelum Anda menghentikan segment, posisi segment saat ini harus Anda simpan. Ketika hendak melakukan resume, posisi yang anda simpan, digunakan untuk mengubah start point playback. Anda mengubah start playback segment menggunakan fungsi SetStartPoint() milik interface IDirectMusicPerformance8. Setelah memanggil SetStartPoint(), Anda memainkan segment seperti biasa dengan PlaySegmentEx().
Ketika selesai dengan DirectX Audio, Anda harus memanggil fungsi CloseDown() milik objek performance. Fungsi ini tidak membutuhkan parameter apa-apa.
Sebelum memanggil CloseDown() ada baiknya anda memanggil Unload() untuk meng-unload segment-segment yang sebelumnya sudah didownload ke performance. Parameternya sama dengan fungsi Download yakni audiopath atau performance di mana segment didownload.
Sebenarnya memanggil Unload() tidak wajib dilakukan ketika menutup performance, karena CloseDown otomatis akan meng-unload segment-segment yang ada. Listing 21 berisi contoh kode bagaimana menutup DirectX Audio.
FSound1.Unload(FPerformance); FPerformance.CloseDown(); FPerformance:=nil;
Loader menggunakan mekanisme cache untuk mempercepat proses playback. Objek yang diciptakan dengan GetObject() atau LoadObjectFromFile() mungkin mereferensi objek lain. Sebuah file MIDI mungkin memiliki referensi ke file MIDI lain. GetObject otomatis akan menciptakan object yang direferensi dan menambahkan ke cache.
Untuk membebaskan object-object tersebut secara menyeluruh, ada beberapa hal yang harus Anda kerjakan.
Jika anda tidak menggunakan object yang mereferensi objek lain, Anda tidak perlu memanggil ReleaseObjectByUnknown() dan CollectGarbage(). Contohnya jika me-load WAV ke segment, Anda tidak perlu melakukan langkah di atas karena WAV tidak mereferensi file eksternal. Namun hal ini adalah kebiasan baik untuk memastikan memori yang kita pergunakan benar-benar dibebaskan semua.
FLoader.ReleaseObjectByUnknown(FSound1); FLoader.CollectGarbage; FLoader:=nil;
Aplikasi demo dapat Anda dapatkan source code-nya di CD/DVD. Demo DM1.dpr berisi demo bagaimana melakukan inisialisasi DirectX Audio dan memainkan segment menggunakan PlaySegment(). Demo DM2.dpr hampir sama dengan DM1, namun yang digunakan adalah PlaySegmentEx().
Demo DM3.dpr adalah perluasan demo DM2.dpr. Di aplikasi ini, kita mampu memainkan beberapa suara sekaligus. Demo DM4.dpr merupakan perluasan DM3.dpr dengan penambahan musik latar berformat MIDI yang akan dimainkan terus menerus sampai aplikasi ditutup.
Secara umum user interface aplikasi demo tampak seperti pada Gambar 3.
Gambar 3. User interface aplikasi demo.
Source code aplikasi demo dapat di download di sini
Anda telah sampai pada bagian akhir artikel ini. Saya harapkan Anda telah mengetahui teknik dasar memanfaatkan DirectX Audio dalam aplikasi Anda. Di artikel ini, Anda telah belajar tentang arsitektur DirectX Audio, melakukan inisialisasi, membaca dan memainkan file suara menggunakan DirectX Audio, serta bagaimana memainkan beberapa suara bersamaan.
Anda suka artikel ini? Bantu website ini berkembang dengan menyumbang. Berapapun jumlahnya akan sangat dihargai.
Atau Anda dapat membantu dengan membuat bookmark.
Bookmark this on Delicious