Make a *.RC file (Unit1.RC), and let it look like this:
#define IDW_SOUND 1000
#ifdef RC_INVOKED
IDW_SOUND WAVE "sound.wav"
#endif
Place the RC file in the same root with Unit1.cpp i Unit1.h.
Also, in the same folder plase your "sound.wav" file (because
of compiling).
Later, when EXE is made, you do not need "sound.wav" any more.
Add (Add to project...) that Unit1.RC to the project.
Later, from the program, you can play the sound like this:
PlaySound( MAKEINTRESOURCE( IDW_SOUND ), HInstance, SND_RESOURCE |
SND_ASYNC );
--
Best regards,
Vladimir Stefanovic
Thanks.
MIDI is a much more complicated beast. You need a MIDI device
installed (supported by an installed sound card, or the software MIDI
player included with Windows XP Pro). Then you'll need the MIDI API
http://tinyurl.com/awvtv functions to open and play a MIDI stream. I
googled and came up with this example: http://tinyurl.com/7nf6z
HTH,
Bruce
TMediaPlayer handles MIDI files but only from disk.
//--- The sound resource header - SoundResource.rh ------------
#ifndef SoundResource_RH
#define SoundResource_RH
#define ID_SoundFileName1WithoutExtension 1000
#define ID_SoundFileName2WithoutExtension 2000
#endif
//--- The sound resource source - SoundResource.rc ------------
SoundFileName1WithoutExtension MIDI SoundFileName1.mid
SoundFileName2WithoutExtension WAVE SoundFileName1.wav
//--- SoundResource.bat ---------------------------------------
rc SoundResource
pause
//--- in the unit ---------------------------------------------
AnsiString Path = "";
//-------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
MediaPlayer1->AutoOpen = false;
MediaPlayer1->Visible = false;
Path = ExtractFilePath( Application->ExeName );
}
//-------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
PlayMidiSound( "SoundFileName1WithoutExtension" );
}
//-------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
::PlaySound( "SoundFileName2WithoutExtension", HInstance, SND_ASYNC | SND_NODEFAULT | SND_NOWAIT );
}
//-------------------------------------------------------------
void __fastcall TForm1::PlayMidiSound( AnsiString ID )
{
HRSRC SoundResource = ::FindResource( HInstance, ID.c_str(), "MIDI" );
if( SoundResource )
{
DWORD Size = ::SizeofResource( HInstance, SoundResource );
if( Size )
{
HGLOBAL SoundLoad = ::LoadResource( HInstance, SoundResource );
if( SoundLoad )
{
LPVOID SoundPointer = ::LockResource( SoundLoad );
if( SoundPointer )
{
MediaPlayer1->FileName = Path + ID + ".mid";
TFileStream *fStream = new TFileStream( MediaPlayer1->FileName, fmCreate );
fStream->Seek( 0, soFromBeginning );
fStream->Write( SoundPointer, Size );
delete fStream;
MediaPlayer1->Open();
MediaPlayer1->Play();
}
}
}
}
}
//-------------------------------------------------------------
Note that if you want to loop the sound, PlaySound has a
SND_LOOP flag. To accomplish the same with the MediaPlayer,
you need to use it's Notify property and OnNotify event to
setup a loop.
~ JD
> What is the best way to play a .wav or .mid file stored in the resource?
The easiest way is via the Win32 Multimedia API PlaySound() function. It
can play sounds from a file, a memory block, or a resource.
Gambit
> HRSRC SoundResource = ::FindResource( HInstance, ID.c_str(), "MIDI" );
<snip>
Look at the TResourceStream class, ie:
void __fastcall TForm1::PlayMidiSound(const AnsiString &ID)
{
AnsiString MediaFileName = Path + ID + ".mid";
TResourceStream *RS = new TResourceStream(HInstance, ID);
try {
TFileStream *FS = new TFileStream(MediaFileName, fmCreate);
try {
FStream->CopyFrom(RS, 0);
}
__finally { delete FS; }
}
__finally { delete RS; }
MediaPlayer1->FileName = MediaFileName;
MediaPlayer1->Open();
MediaPlayer1->Play();
}
Gambit
Another Stream class!!
> MediaPlayer1->FileName = MediaFileName;
> MediaPlayer1->Open();
> MediaPlayer1->Play();
The way it's coded, won't TMediaPlayer throw if extraction
from the resource fails?
~ JD
I couldn't get it to play MIDI files (?) and I tried all 3.
~ JD
> Another Stream class!!
The VCL has many stream classes.
> The way it's coded, won't TMediaPlayer throw
> if extraction from the resource fails?
No, because it won't get that far. If extraction fails, an exception will
be thrown before TMediaPlayer is ever touched.
Gambit
> I couldn't get it to play MIDI files (?) and I tried all 3.
PlaySound() only supports waveform audio.
Gambit
Any idea how to tell when the .WAV file is finished? I want to try this in a
test application and have it continually loop or have a second .WAV start
after the first one ends.
> Any idea how to tell when the .WAV file is finished?
Use SND_SYNC instead of SND_ASYNC when calling PlaySound(). Then
PlaySound() won't return until the sound is finished playing.
> I want to try this in a test application and have it continually loop
PlaySound() has a SND_LOOP flag available as well. You have to use
SND_ASYNC with it, though. For example:
void __fastcall TForm1::StartLoop()
{
PlaySound(MAKEINTRESOURCE(IDW_SOUND), HInstance, SND_RESOURCE |
SND_ASYNC | SND_LOOP);
}
void __fastcall TForm1::StopLoop()
{
PlaySound(NULL, NULL, 0);
}
> or have a second .WAV start after the first one ends.
Using SND_SYNC, you can call PlaySound() again on a second sound immediately
after PlaySound() finishes playing the first sound.
Gambit