📄 midiplayer.cs
字号:
// MidiPlayer.cs
// A simple wrapper around the DirectX 7 MIDI-playback service
// NOTE: I'm using DX7 instead of DX8 because DX7 works on DX8 machines, but not vice versa.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using DxVBLib;
namespace EmbeddingUnmanagedResourcesSample {
class MidiPlayer : Component {
public MidiPlayer() {
// A loader object is what parses the data from a file
// on the hard drive to the area in memory.
loader = dx.DirectMusicLoaderCreate();
// A performance controls the music. It looks after
// sending data to the music port, setting options
// converting time sigs. etc...
// A performance is what organises the events
// think of it as a conductor - syncronising things
// setting things up; looking after the individual pieces
// of music.
perf = dx.DirectMusicPerformanceCreate();
// Set it's options - these options should be standard
// across most projects.
perf.Init(null, 0);
perf.SetPort(-1, 80);
perf.SetMasterAutoDownload(true);
Volume = 75;
}
public int Volume {
// TODO: get
set {
// The value can be any number between 0 (mute) and 100 (max).
// The formula just uses this number to create a volume DM can understand.
if( value < 0 || value > 100 ) throw new ApplicationException("Volume must be between 0 and 100");
perf.SetMasterVolume(value * 42 - 3000);
}
}
public void LoadFromFile(string fileName) {
// A segment is where the actual data is stored;
// like a buffer or a surface in other DirectX objects
// Use the loader object to create us a music buffer
// NOTE: Needs to be of type "DMSEG"
seg = loader.LoadSegment(fileName);
// Set the format of the segment to be a MIDI
seg.SetStandardMidiFile();
}
// TODO: Need to support numberic IDs, too
// (i.e. using a managed implementation of MAKEINTRESOURCE);
public void LoadFromResource(string fileName, string id) {
// NOTE: If this fails, try passing in the ID as upper case
seg = loader.LoadSegmentFromResource(fileName, id);
seg.SetStandardMidiFile();
}
public void Start() {
if( seg == null ) throw new ApplicationException("Must load a MIDI resource before starting");
// Make sure we're stopped before starting
Stop();
// This variable lets us know what the music is
// doing. At the simplest level this is "am I playing?"
// "am i stopped?" etc.
// This is all it takes to start playing.
// The last variable states where to start playing from;
// in this case "0", which means the beginning.
segstate = perf.PlaySegment(seg, 0, 0);
}
public void Stop() {
if( perf != null ) {
perf.Stop(seg, segstate, 0, 0);
if( segstate != null ) {
Marshal.ReleaseComObject(segstate);
segstate = null;
}
}
}
protected override void Dispose(bool isManagedDispose) {
// Otherwise, it's the finalizer firing and all
// of our managed references will be handled for us
if( isManagedDispose ) {
Stop();
if( perf != null ) {
perf.CloseDown();
if( seg != null ) {
Marshal.ReleaseComObject(seg);
seg = null;
}
Marshal.ReleaseComObject(perf);
perf = null;
}
}
// Let the base class have a chance, too
base.Dispose(isManagedDispose);
}
// DirectX 7
DirectX7 dx = new DirectX7Class();
DirectMusicLoader loader;
DirectMusicPerformance perf;
DirectMusicSegment seg;
DirectMusicSegmentState segstate;
/*
* DirectX 8
* DirectX8 dx = new DirectX8Class();
* DirectMusicLoader8 dml = dx.DirectMusicLoaderCreate();
* DirectMusicPerformance8 dmp = dx.DirectMusicPerformanceCreate();
* DMUS_AUDIOPARAMS dmA = new DMUS_AUDIOPARAMS();
* DirectSound8 ds = null;
* dmp.InitAudio(Handle.ToInt32(), CONST_DMUS_AUDIO.DMUS_AUDIOF_ALL, ref dmA, ref ds, CONST_DMUSIC_STANDARD_AUDIO_PATH.DMUS_APATH_SHARED_STEREOPLUSREVERB, 64);
* DirectMusicSegment8 seg = dml.LoadSegment(@"C:\temp\MIDIDemo\sample4.mid");
* seg.Download(dmp.GetDefaultAudioPath());
* dmp.PlaySegmentEx(seg, 0, 0, null, null);
*/
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -