How to play a sound from an embedded resource file? (.resx file)?

R

raylopez99

I have the latest version of Visual Studio 2008 Professional, which
allows you to create resource files (this is the .resx file, no?),
unlike the Express version, which does not.

I am trying to cut and paste code that MSDN recommends for playing a
simple wav file from inside an embedded file, like presumeably the
'resources' file .resx is. I want to embed the .wav file in a
'resource file' since I don't want the user storing the file on their
hard drive.

Using the Wizard, and clicking on various links, I was able to create
a resource file (.resx file?) that plays a small sound, 25 kb, that I
call "mywav.wav" (it plays this sound when you click on the icon for
the audio file in Visual Studio, in the .resx file and accompanying
files*). The .resx file only has this wav in it, nothing else, and
the .resx resource file is called "myaudio.resx".

I used the below code, which is pretty generic, but I cannot get
anything but a small 'ding' (which I think is the default Windows
error sound), but not the sound of "mywav.wav". I tried various
permutations of the string. Apparently this ADO.NET type language is
not strongly typed since it compiles with no problems, but it doesn't
run right...what is wrong?

RL

* I notice the .resx file is in XML format and contains a string for a
"PublicKeyToken". Perhaps, since I've never used this before, I need
to somehow log in for Visual Studio under my Administrator account (I
am using XP as the OS), and reset something?

//a class method declared and used inside of form Form 1, from an
object instantiated as "myClassObject"

public void playSoundFromResource(object sender, EventArgs e)
{
System.Reflection.Assembly a =
System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Stream s =
a.GetManifestResourceStream("<myaudio.resx>.mywav.wav"); //<--note
string--is this correct?
SoundPlayer player = new SoundPlayer(s);
player.Play();
}


// I use it on a button in Form form 1--when I click on a button, the
mywav.wav does not play, but a small 'ding' does...why?

private void button1_Click(object sender, EventArgs e)
{
myClassObject.playSoundFromResource(sender, e);
}
 
F

Family Tree Mike

You don't say where you got the code from but, I just add the wave file to
the project. In the properties for the file you can set the build action to
"Embedded Resource", then use the code you have to get the file into the
player.

This line: a.GetManifestResourceStream("<myaudio.resx>.mywav.wav");
should be: a.GetManifestResourceStream("ProjectNamespace.mywav.wav");
 
R

raylopez99

You don't say where you got the code from but, I just add the wave file to
the project.  In the properties for the file you can set the build action to
"Embedded Resource", then use the code you have to get the file into the
player.

This line: a.GetManifestResourceStream("<myaudio.resx>.mywav.wav");
should be: a.GetManifestResourceStream("ProjectNamespace.mywav.wav");

FTM--I tried your suggestion, and it failed.

After a lot of research on the net, I concluded it's probably a bug in
the Resource Manager of Visual Studio 2008, which is buggy. Others
are having the same problem. A quick and dirty workaround is to
abandon trying to use resource files, and simply externally reference
the audio .wav file.

Below is some simple code that works. When distributing your program
to users, just make sure the .wav file you want to play is found in
the same directory as the binary executable .exe file of your final
release.

The name of the file you would want to play below is called
"myWavAudioFile.wav" . This .wav file should be placed in the same
path as where the \bin\Release folder is in Visual Studio, which is
where your final release of the .exe executable of your program is
found. The string path_where_EXE_file_Is will get the path string of
whatever directory the end user of the program has the program in. The
two strings are concatenated and used to set the .SoundLocation
property of the SoundPlayer. Don't forget to add try/catch blocks
(even if empty) to guard against the audio file somehow not being
present, which will cause an exception, and without the try/catch
blocks a system level exception that will stop your program.

RL

// this code works use library-- using System.Media;

try
{
System.Media.SoundPlayer myPlayer = new
System.Media.SoundPlayer();
string path_where_EXE_file_Is =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string s = "\\myWavAudioFile.wav"; //name of the audio wav
file to be played; don't forget the extra backslash, \\
string s1 =path_where_EXE_file_Is + s;
myPlayer.SoundLocation = @s1;
myPlayer.Play();
}
catch
{
//optionally do stuff here if file not found, or just leave blank
//need to have try/catch blocks in case audio file not found,
otherwise throws a system level exception
}
 
F

Family Tree Mike

Sorry what I suggested did not work for you. I don't know what you did that
I did not.

Your code should not need to set the file directory if it is in the same
folder as the executeable, as that is where it would open from by default.

You don't say where you got the code from but, I just add the wave file to
the project. In the properties for the file you can set the build action
to
"Embedded Resource", then use the code you have to get the file into the
player.

This line: a.GetManifestResourceStream("<myaudio.resx>.mywav.wav");
should be: a.GetManifestResourceStream("ProjectNamespace.mywav.wav");

FTM--I tried your suggestion, and it failed.

After a lot of research on the net, I concluded it's probably a bug in
the Resource Manager of Visual Studio 2008, which is buggy. Others
are having the same problem. A quick and dirty workaround is to
abandon trying to use resource files, and simply externally reference
the audio .wav file.

Below is some simple code that works. When distributing your program
to users, just make sure the .wav file you want to play is found in
the same directory as the binary executable .exe file of your final
release.

The name of the file you would want to play below is called
"myWavAudioFile.wav" . This .wav file should be placed in the same
path as where the \bin\Release folder is in Visual Studio, which is
where your final release of the .exe executable of your program is
found. The string path_where_EXE_file_Is will get the path string of
whatever directory the end user of the program has the program in. The
two strings are concatenated and used to set the .SoundLocation
property of the SoundPlayer. Don't forget to add try/catch blocks
(even if empty) to guard against the audio file somehow not being
present, which will cause an exception, and without the try/catch
blocks a system level exception that will stop your program.

RL

// this code works use library-- using System.Media;

try
{
System.Media.SoundPlayer myPlayer = new
System.Media.SoundPlayer();
string path_where_EXE_file_Is =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string s = "\\myWavAudioFile.wav"; //name of the audio wav
file to be played; don't forget the extra backslash, \\
string s1 =path_where_EXE_file_Is + s;
myPlayer.SoundLocation = @s1;
myPlayer.Play();
}
catch
{
//optionally do stuff here if file not found, or just leave blank
//need to have try/catch blocks in case audio file not found,
otherwise throws a system level exception
}
 
F

Family Tree Mike

Also, in the case you want the file along side the executable, add the .wav
file to the project and set the "Copy to output" property to "Copy always"
or "Copy if newer". I believe that a setup project will pick this up for
installing.
 
B

Bob Powell [MVP]

Place the sound in the application resources as an embedded resource.

private void button1_Click(object sender, EventArgs e)

{

SoundPlayer sp = new SoundPlayer();

sp.Stream =
this.GetType().Assembly.GetManifestResourceStream("PlaySoundFromResource.ir_begin.wav");

sp.Play();

}



This works fine for me.


--
--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 
R

raylopez99

Place the sound in the application resources as an embedded resource.

private void button1_Click(object sender, EventArgs e)

{

SoundPlayer sp = new SoundPlayer();

sp.Stream =
this.GetType().Assembly.GetManifestResourceStream("PlaySoundFromResource.ir _begin.wav");

sp.Play();

}
\

Thanks but this did not work either (I tried your version and a slight
variation, below***). The problem is with the resource editor of
Visual Studio--I've spent several hours today surfing the net and I've
seen a half dozen posts like mine, some from even more experienced
programmers, all pretty much having the same problem. I've installed
many different visual studios, going back to VS 98 I think, and they
all have not been disinstalled. Consequently the settings interfere
sometimes. For a while I had problems getting the Debugger to work,
when I installed Visual Studio 2008 Professional. It did not help
that I had installed the VS2008 Express (free) edition,which does not
have Resource file support (explicitly). In fact, this might be at
work now.

Further complicating things, I can use the Settings.Settings file OK
to store settings (very useful) inbetween an app being fired up, I can
set (change) the .ico file for the icon of a form, I can create (but
not use) bitmaps using the Resource Editor of VS08, I can see "loaded"
the values into the XML-format .resx file, and you can see the strings
holding the resources such as .wav, .bmp, etc, but I can't use them,
no matter what settings (typically "build action: embedded
resource"). I give up. Besides I'm starting to like putting the
graphics and audio files in a directory--it gives the user a feeling
of more control, and doesn't hide what is being use by the app. Sour
grapes perhaps.

Also another potential problem: perhaps I have to set up Strong-Name
Signing for Managed Applications, see http://msdn.microsoft.com/en-us/library/h4fa028b.aspx

Perhaps, since I'm just a ordinary User and not an Administrator, I
have to do this first from Admin account (using XP as an OS right
now).

BTW, I read on the net that Vista totally revamps audio, so anything I
learn now will be obsolete for WPF / Vista+ API, so I'm not going to
sweat it, though it would be nice to get the resource file working.

Thanks for your time.

RL


Here is the variation, as my .wav is called Chime (case sensitive)

*** SoundPlayer sp = new SoundPlayer();
sp.Stream =

this.GetType().Assembly.GetManifestResourceStream("Chime.wav");
sp.Play();
 
R

raylopez99

Hi FTM and Bob Powell,

I did get Resource File to play a sound (and I don't know how I
managed it either, but I kept plugging away), however, on occasion
(about every other play) the sound played has unacceptable distortion
and noise... some very high pitched sounds. Apparently others have
noticed this as well.

The only thing I could think of is that the audio stream perhaps is
not being shut down properly, and the garbage collection is not being
performed on the stream in time, and thus noise creeps in from the
system itself (just wildly guessing**).

Any suggestions appreciated. Below is the information including
another blogger, who mentions distortion and noise when playing sounds
embedded in the resource file. BTW this noise does not occur when I
"point" to a .wav file as I indicated in the 'hard coding' example
earlier, so it's unique to resource files containing audio.

RL

//both these versions 'worked' (but with occasional noise and
distortion)

//VERSION ONE

try
{

SoundPlayer sp = new
SoundPlayer(MyNameSpace.Properties.Resources.MySound);

sp.Stream =
this.GetType().Assembly.GetManifestResourceStream("MySound.wav");

if (MyNameSpace.Properties.Resources.MySound != null)
{
using (sp.Stream)
{
sp = new
SoundPlayer(MyNameSpace.Properties.Resources.MySound);
//note: do not use extension .wav on MySound, just the name itself!
sp.Play();
}
}

Catch {}
/////////////////////////////////////////////////////

// VERSION TWO

try {

if (MyNameSpace.Properties.Resources.MySound != null)
{
using (MyNameSpace.Properties.Resources.MySound)

{
System.Media.SoundPlayer myPlayer = new
System.Media.SoundPlayer(MyNameSpace.Properties.Resources.MySound);
//this was key: MySound.wav does NOT use the extension!
myPlayer.Play();
}
}

{

catch {}

////////// from a blog, talking about WPF 2008 audio distortion when
using a resource file, but equally applicable for WinForms ///////////


http://vbfeeds.com/post.aspx?id=5512

3. Audio File as Resource (Frustration #2)

I wasn't going to include this option because it has generally
caused me more trouble than it's worth (especially bearing in mind
that there are several relatively trouble-free alternatives).
However, you can add a wav file as a Project Resource as normal and
then play that Resource via a Stream.

Even with small, well tested files I often found that using this
approach I would get a lot of unacceptable sound distortion (actually
additional unrelated sounds to that expected). I have tried it on
several PCs, each with different sound card configurations and the
problems occur on them all.

////////////

** Yet another blogger mentions, in an unrelated post, how the C#
Garbage collector is aggressive and will collect garbage before going
out of scope, so perhaps this is a problem here? Just grasping at
straws--RL

"I wrote above that I initially thought that objects are destroyed
"somewhen after they go out of scope", but in reality it seems to be
far, far worse. As it turns out, the JIT compiler can do "lookahead
optimization", and may mark any object for collection after what it
considers it's "last use", ignoring scope!"
 
F

Family Tree Mike

Since SoundPlayer has a Dispose method, you should call it or use it within
a using() block. That's the only thing that jumps out at me.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top