I'm trying to play a sound file in monotouch but it gets cut off after a second or two. Here is the code I'm using to play the sound:
SoundFileName = filename;
var sound = SystemSound.FromFile(filename);
sound.PlaySystemSound();
It's an MP3 file that I'm trying to play. Again, I hear it for a brief second and then it gets cut. I added a thread.sleep() line afterwards and THEN it'll play throughout.
But that's not ideal because the length of the mp3 files that I'm playing could vary. Any help would be greatly appreciated. Thank you.
You need to declare your sound object at the form or class level. In your posted sample, sound is only scoped to the function, so as soon as the method ends the variable goes out of scope and is disposed before the sound finished playing. Thread.sleep works because that call prevents the method from ending for a while (and thus prevents sound from going out of scope).
You may also want to look at this question: Playing a sound with MonoTouch
I don't think SystemSound is intended to use with MP3's of open duration.
Related
I'm making a game to learn how to properly use C#, but the sounds that I use don't play as intended. They make no errors, but play late and the file seems cut.
I'm using WinForms, so I tried a SoundPlayer with a Stream, or tried with Visual Basic's Audio class.
I also tried to make a dictionary full of streams, or full of SoundPlayer, but it didn't change anything.
It work when I use the AudioPlayMode.WaitToComplete, but it isn't what I want.
Thanks in advance !
I've figured it out. I just put the audio in a Thread, and put Audio.WaitToComplete in it.
I have a single WMA file which contains lots of different pieces of audio.
Is there any way I can play part of a sound stream?
Something like:
public static void Play(Stream soundStream, long start, long end);
You may be able to do this using NAudio, it is a audio library for .Net.
Using the example here I was able to throw a quick test application up to try it. Using the WaveSteam.Skip(int seconds) method you are able to start at a specific position in the file. I have not been able to work out how to get the end position though. Below is the modified sample that starts a wma file at the 30 second mark:
IWavePlayer waveOutDevice = new WaveOut();
WaveStream mainOutputStream;
WaveChannel32 volumeStream;
WaveStream wmaReader = new WMAFileReader(#"F:\My Music\The Prodigy\Music for the Jilted Generation\01 Intro.wma");
volumeStream = new WaveChannel32(wmaReader);
mainOutputStream = volumeStream;
mainOutputStream.Skip(30); //start 30 seconds into the file
waveOutDevice.Init(mainOutputStream);
waveOutDevice.Play();
The above sample omits the cleanup code to stop playback and dispose of the streams however. Hope that helps a bit.
Not in the way you want, no.
I assume this is within a WinForms or WPF context. The solution is to host the WMP ActiveX control in your project, then load the WMA file into it and set the Position/Seek property and then play it for a while and stop it when the Timer reaches a certain point. I don't believe the WMP ActiveX control has a timer event, so you'd need to watch it on another thread and stop the playback when it's reached.
It's a hack, but should work. You should be able to get something that "works" within a few hours if you're familiar with hosting ActiveX controls within .NET applications. Note that you'll want to make your application x86-only because of compatibility issues with the 64-bit WMP ActiveX control.
The, much harder, alternative is to work with DirectShow from within your application and create a Render Graph for WMA files and do the manipulation, seeking and playback yourself. DS has a very steep learning curve, expect this to take you at least a few days to even a few weeks if you've never worked with COM before.
I wish to write a C# WinForms application that can play a WAV file. While playing the file, it shows a waveform (similar to an oscilloscope).
At the same time, a user can record sound via the microphone, attempting to follow the original sound played (like a karaoke). The program displays the waveform of the recorded sound real-time, so comparisons can be seen from the waveform display of the original
wave file and the recorded one by the user. The comparisons will be done as in the difference in time (the delay) of the original and recorded sound. The waveform displays don't have to be very advanced (there is no need for cut, copy or paste); just being able to see it with a timeline would suffice.
I hope this is clear enough. Please do not hesitate to ask for more clarification if it's not clear. Thank you very much.
You can do what you want with C#, but it isn't going to work like you think. There is effectively no relationship at all between how a recording looks in an oscilloscope-type display and how that recording sounds to a human ear. So, for example, if I showed you two WAV files displayed in an oscilloscope display and told you that one recording was of a tuba playing and the other was of a person speaking a sentence, you would have no idea which was which just from looking at them.
If you want to compare a user's sounds to a pre-recorded WAV, you have to get more sophisticated and do FFT analysis of both and compare the frequency spectra, but even that won't really work for what you're trying to do.
Update: after some thought, I don't think I fully agree with my above statements. What you want to do might sort of work if what you want to do is to use the oscilloscope-type effect to compare the pitch (or frequency) of the WAV and the person's voice. If you tuned the oscilloscope to show a relatively small number of wavelengths at a time (like 20, maybe), the user would be able to quickly see the effect of raising or lowering the pitch of their voice.
I have a small sample C# app that I wrote about 2 years ago that does something kind of like this, only it displays an FFT-produced spectrograph instead of an oscilloscope (the difference is basically that a spectrograph shows frequency-domain information while an oscilloscope shows time-domain information). It's realtime, so you can talk/sing/whatever into a microphone and watch the spectrograph change dynamically.
I can dig this out and post the code here if you like. Or if you want the fun of doing it all yourself, I can post some links to the code resources you'd need.
The NAudio library has plenty of functionality that will (possibly) give you what you need. I've used it in the past for some simple operations, but it is much more powerful than I've had need to use.
#ZombieSheep
Naudio is indeed useful, but it has limitations. For example, there is not much control over the waveform display, it cannot be cleared and redrawn again. Besides, if it gets too long its impossible to scroll back to see the waveform in the front part. One more thing is that it only works with playing the sound but does not work with recording the sound.
Thank you.
I'm looking for an audio library that works with .NET that allows for smooth looping. I've tried DirectX AudioVideoPlayback and Mentalis. Both are easy to use, but the looping skips a bit. I'm wondering if that's my fault or theirs. I have sound samples that I know can loop cleanly (WinAmp can do it fine) but I can't get my C# app to do the same. What library could I use, or what could I fix in my app to get it to loop cleanly with the libraries I have?
UPDATE: FMOD has been able to loop my audio, but the problem is that the .net wrapper I have only loads files one way. I can't play a sound effect more than once because they get disposed when playback finishes, and sometimes it hangs whenever a sound is supposed to be played. I know I could just reload the sound to play it again, but I don't want to hit the disk every time a gunshot is fired. Should I just reach into the C++ layer myself and skip the .NET wrappers?
You could try FMOD which is free for non-commercial use.
I would double-check that the sound really loops cleanly - specifically, that the first sample and the last sample are close (or equal), otherwise you'll hear a click. WinAMP could conceivably do some special processing to eliminate the click.
UPDATE: FMOD comes with a whole bunch of samples in C# that show the right way to do stuff. The example called "3d" shows, among other things, a cleanly looping sound. You should be able to rip out the code that handles the looping without utilising the 3D features.
I have a C# game program that i'm developing. it uses sound samples and winsock.
when i test run the game most of the audio works fine but from time to time if it is multiple samples being played sequentially the application form shakes a little bit and then goes back to its old position.
how do i go about debugging this or present it to you folks in a manageable manner? i'm sure no one is going to want the whole app code in fear of virus attacks.
please guide me..
EDIT: i have not been able to pin down any code section that produces this result. it just does and i cannot explain it.
EDIT: no the x/y position are not changing. the window like shakes around a few pixels and then goes back to the position were it was before the shake.
if (audio)
{
Stream stream;
SoundPlayer player;
stream = Properties.Resources.ResourceManager.GetStream("_home");
player = new System.Media.SoundPlayer(stream);
player.PlaySync();
player.Dispose();
string ShipID = fireResult.DestroyedShipType.ToString();
stream = Properties.Resources.ResourceManager.GetStream("_" + ShipID);
player = new System.Media.SoundPlayer(stream);
player.PlaySync();
player.Dispose();
stream = Properties.Resources.ResourceManager.GetStream("_destroyed");
player = new System.Media.SoundPlayer(stream);
player.PlaySync();
player.Dispose();
}
can you see anything in the above code that would produce this shake?
EDIT: yes the code is being executed within a: this.Invoke(new Action(delegate(){ ....})); could this be it? how do i resolve this?
EDIT:
stream = Properties.Resources.ResourceManager.GetStream("_destroyed");
player = new System.Media.SoundPlayer(stream);
player.PlaySync();
player.Dispose();
stream.Dispose();
if the take out the above code, then it works fine! any ideas?
EDIT: i replaced the line with:
stream = Properties.Resources.ResourceManager.GetStream("_destroyed");
to a different file name but the problem is still there but at least it is not the audio file is corrupt.
EDIT: MSN when someone sends a nudge? it is bit like that but only happens 2 or 3 times.
EDIT: Are you using any 3rd party libraries? - no i am not using any 3rd party libs.
EDIT: it seems no matter what file, the 3rd sample always causes this.
EDIT: happens everywhere i use sound samples. if i play 3 samples, the situation happens.
EDIT: #nobugz: yes think you are right. the problem is holding up the UI thread for too long. as i have tried just using a merged audio file and the problem is there given its original duration.
EDIT: i solved this issue by putting Application.DoEvents(); after each sample play command. no shakes :)
EDIT: the above solution did not really work. as the number of player samples grew the application GUI got stuck again. a solution using QueueUserWorkItem has been employed instead. this still remains to be proven as a satisfactory solution as cross therading occurs i.e. a new thread of samples can be started while an old one is still playing.
will update this as more knowledge comes to light.
Calling PlaySync on the UI thread isn't so great. It will make your main window unresponsive as your UI thread is busy waiting for the sound to finish, it doesn't get around to pumping messages like it should do. If that takes long enough, Windows steps in and overlaps the window with a "ghost", it usually says "Not Responding" in the title bar (if it has one). This ghost window might not quite match your own window, that could explain the "shaking".
Using Play() instead will solve that problem. But gets you a new one, sequencing sounds becomes difficult. Making the calls from a thread can solve both. Check out NAudio for better control over sound.
Make a copy of your program. Delete as many game elements from the copy as possible. Remove modules, chop out game logic, shift functions between classes to reduce abstraction (so that you can delete classes), and generally hack up the game.
Each time you do so, check if the bug still exists. Initially you'll be deleting bigger chunks of the program but over time the amount of deletion will reduce.
If you find something which, when deleted, fixes the bug, there are two possibilities: Either you found the bug, or there is some sort of synergy with the rest of the program to cause the bug. In the latter case, continue deleting more of the program.
Eventually, you will end up with a minimal program that has the bug. Post that here (or in a pastebin if it's too big).
This is one of the last-resort strategies I use when I encounter a bug that I am unable to locate at all.