Playing MIDI Files Directly From The Resource

Introduction
Public Interface
Overridables
Usage
Download
Comments
 

Introduction (back to top)

This class is a slightly modified "spin off" from the CGTetris application. It is based on a sample in the DirectX sdk (called mstream). The conversion into a C++ class makes it much easier to use. The CMIDI class makes it easy to play a MIDI file directly from the resource (without copying it into a temporary file). One can use the class to play MIDI files, too. In this case you have to load the entire file into memory and to pass the pointer to the beginning of the buffer to the Create() method.

Public Interface (back to top)

// create the MIDI object. You cannot use a MIDI object before
// you've "Create()"ed one!
BOOL Create(LPVOID pSoundData, DWORD dwSize, CWnd * pParent = 0);
BOOL Create(LPCTSTR pszResID, CWnd * pParent = 0);
BOOL Create(UINT uResID, CWnd * pParent = 0);

// Play the MIDI file. Normally the playback will stop after
// the MIDI played off.
BOOL Play(BOOL bInfinite = FALSE);

// usually you should never set "bReOpen" to FALSE
// unless you're absolutly sure you will
// not reuse the MIDI object. Normally only the
// destructor of the class should set this flag
BOOL Stop(BOOL bReOpen = TRUE);

BOOL IsPlaying() const;

BOOL Pause();
BOOL Continue();
BOOL IsPaused() const;

// Set playback position back to the start
// normally there is no need to call this method directly.
BOOL Rewind();

// Get the number of volume channels
DWORD GetChannelCount() const;

// Set the volume of a channel in percentage. (default 100%)
// Channels can be addressed from 0 to (GetChannelCount()-1)
void SetChannelVolume(DWORD channel, DWORD percent);

// Get the volume of a channel (in percentage)
DWORD GetChannelVolume(DWORD channel) const;
 
// Set the volume for all channels in percentage
void SetVolume(DWORD percent);

// Get the average volume for all channels (in percentage)
DWORD GetVolume() const;

// Set the tempo of the playback. (default 100%)
void SetTempo(DWORD percent);

// Get the current tempo (in percentage)
DWORD GetTempo() const;

// You can (un)set an infinite loop during playback.
// Note that "Play()" overrides this setting!
void SetInfinitePlay(BOOL bSet = TRUE);

The CMIDI class sends the message WM_MIDI_VOLUMECHANGED to its owner window (if one is set via Create()), if the volume changed during playback in another way than explicitly set by the class (a MIDI stream can control its volume by itself). The WPARAM parameter of the message is a pointer to the CMIDI object that sent the message. The LOWORD of the LPARAM parameter describes the channel that changed volume and the HIWORD is the new volume in percentage. The WM_MIDI_VOLUMECHANGED message is #define'd as WM_USER+23.

Overridables (back to top)

// NOTE THAT, IF YOU OVERRIDE ONE OF THESE METHODS, YOU MUST CALL
// THE BASE CLASS IMPLEMENTATION, TOO!

// called when a MIDI output device is opened
virtual void OnMidiOutOpen();
 
// called when the MIDI output device is closed
virtual void OnMidiOutClose();

// called when the specified system-exclusive or stream buffer
// has been played and is being returned to the application
virtual void OnMidiOutDone(MIDIHDR &);

// called when a MEVT_F_CALLBACK event is reached in the MIDI output stream
virtual void OnMidiOutPositionCB(MIDIHDR &, MIDIEVENT &);

See the sample for how you could use these overridables. A derived CMyMidi class is inside MidiSampleDlg.h.

Usage (back to top)

The source consists of 2 files:
MIDI.[h|cpp]

Add a MIDI resource to your application (from the Menu Insert->Resource->import->*.mid->Custom Type MIDI).
"Create()" your CMIDI (derived) object giving it the resource-id of your MIDI resource. Now you can call Play(), Pause(), Stop() etc.

Download(back to top)

Download Demo Project - 44 KB

Download Sources - 14 KB



Comments

  • How to play simultaneous two midi file ?

    Posted by Legacy on 04/07/2003 12:00am

    Originally posted by: Peewoow

    I have donwloaded the CMidi stream on codeguru and i must admit this is a good piece of code.
    
    

    I have some question regarding the API midistream and how using this class:

    Is it possible to open two stream sat same and play them together ? Like doing with the CMidi class:

    CMidi player1;
    player1.create(IDM_MIDI_SONG1);
    player1.play();

    CMidi player2;
    player2.create(IDM_MIDI_SONG1);
    player2.play();

    I always have an error. Maybe i have to change something in the CMidi implementation, or it is maybe impossible to do that with the Win32 API ?

    However if i play a midi file with the classes and i open in same time a midi file with the windows media player, both are played without any problem.

    Any help are welcome .. :) and good job again ..

    Reply
  • Great class...

    Posted by Legacy on 11/25/2002 12:00am

    Originally posted by: Mykel

    Very nice class... I was searching the web for exactly
    
    this class. Playing a midi file from a resource is what I
    needed. And with this class I have a couple of nice
    functions in addition to that. ;-)

    And the class is totally easy to use... keep o the great
    coding!! And thx for sharing!


    Best regards,
    Mykel

    Reply
  • Is there any C++ Class for Low-Level MIDI control?????

    Posted by Legacy on 07/09/2002 12:00am

    Originally posted by: PinkSpider

    I mean it can control such low-level element
    like MIDI-Event

    thank you!

    Reply
  • is there Any Low-Level MIDI Class??? or SDK??????

    Posted by Legacy on 07/08/2002 12:00am

    Originally posted by: PinkSpider

    thank you very much!!!!!~~~~~~

    Reply
  • is there Any Low-Level MIDI Class??? or SDK??????

    Posted by Legacy on 07/08/2002 12:00am

    Originally posted by: PinkSpider

    thank you very much!!!!!~~~~~~

    Reply
  • Midi

    Posted by Legacy on 03/07/2002 12:00am

    Originally posted by: SRINIVAS

    I have a sound bank containing presets..
    How to assign Preset object to the Midi channel.
    and also i have to retrive channel number of that preet while playing.
    My Midi Message should take
    (CHANNEL NUMBER,keyrange,velocityrange,status)
    thanks
    srinivas

    Reply
  • Thanks !!!!

    Posted by Legacy on 03/05/2002 12:00am

    Originally posted by: Moorak, Choi

    Thank you so much!!!!

    Your source code is very nice
    to understand MIDI files.


    Reply
  • Non MFC version?

    Posted by Legacy on 02/28/2002 12:00am

    Originally posted by: Neale Davidson

    Any chance you can clean off the MFC from the routines and just use straight C and C++? This would be perfect for a couple of a games that I've been doing, but I don't use the MFC.

    I tried stripping it, but I'm a little wary of breaking all the code inside.

    Reply
  • load new Midi resource in same instance?

    Posted by Legacy on 11/28/2001 12:00am

    Originally posted by: Mike

    how can I load a different "MIDI" resource. I would like to switch between MIDIs on the same dialog.

    Reply
  • playing from file code here

    Posted by Legacy on 10/22/2001 12:00am

    Originally posted by: hobnob

    CFile file;
    if(!file.Open( "c:\\1.mid", CFile::modeRead) ) return FALSE;
    LPVOID lpBuffer = ::GlobalAlloc(GMEM_FIXED, file.GetLength());
    m_midiMusic.Create(lpBuffer,file.ReadHuge((LPSTR)lpBuffer,file.GetLength()));

    hobnob
    http://www.traction-software.co.uk

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

  • Learn How A Global Entertainment Company Saw a 448% ROI Every business today uses software to manage systems, deliver products, and empower employees to do their jobs. But software inevitably breaks, and when it does, businesses lose money -- in the form of dissatisfied customers, missed SLAs or lost productivity. PagerDuty, an operations performance platform, solves this problem by helping operations engineers and developers more effectively manage and resolve incidents across a company's global operations. …

Most Popular Programming Stories

More for Developers

RSS Feeds