Playing part of a sound (WMA) file in C# - c#

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.

Related

How to programmatically control VLC seek in milliseconds?

I'm writing an app in C# that's controlling two VLC instances via VLC's remote control interface. I need to be able to control the position in the stream of each instance as much as possible. The RC seek command only gives control in seconds so any fraction of a second is impossible.
Does anyone have a recommendation that will allow me to control seek to milliseconds in C#? I've looked at C# wrappers but none are maintained for the current version of VLC. I'd like to continue to use the RC interface for simplicity if possible.

Windows Mobile - 2 Way Call Recording (C#)

I need to implement 2 way (caller and receiver) call recording on Windows Mobile. I have gone through many forums and articles saying that it's hardware limitation and is not possible on all phones. I have downloaded one application from http://www.resco.net/pocketpc/audiorecorder/ which is running perfect on my phone and has 2 way recording capability.
Is there any possibility of implementing same using .NET CF 2.0 (managed or unmanaged. although, managed is prefered.).
EDIT: I found this sample, but not able to give the length of recording dynamically. I need to start when the call is received and stop when call is ended. So, length is not known at the time of recording.
I Used OpenNETCF.Media.WaveAudio.Recorder for 2 way call recording.
The only problem I faced was, Dynamic length for recording. I solved that by using Recorder.DoneRecording event. I created new .WAV file in each Recorder.DoneRecording and combining all .WAV files using this at the end of recording (using Stop() method).

C# audio library with smooth looping?

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.

WinForms Application Form "Shakes" When Audio Playing

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.

Pass texture using pointer across process

It's hard to put this into the title, so let me explain.
I have an application that uses Direct3D to display some mesh and directshow(vmr9 + allocator) to play some video, and then send the video frame as texture to the Direct3D portion to be applied onto the mesh. The application needs to run 24/7. At least it's allowed to be restarted every 24hours but not more frequent than that.
Now the problem is that directshow seems to be giving problem after a few hours of playback, either due to the codec, video driver or video file itself. At which point the application simply refuse playing anymore video. But the Direct3D portion is still running fine, mesh still displayed. Once the application is restarted, everything back to normal.
So, I'm thinking of splitting the 2 parts into 2 different process. So that when ever the video process failed to play video, at least I could restart it immediately, without loosing the Direct3D portion.
So here comes the actual question, whether it's possible to pass the texture from the video player to the direct3d process by passing the pointer, aka retrieve the texture of another process from pointer? My initial guess is not possible due to protected memory addressing.
I have TCP communication setup on both process, and let's not worry about communicating the pointer at this point.
This might be a crazy idea, but it will work wonder of it's ever possible
Yes you can do this with Direct3D 9Ex. This only works with Vista and you must use a Direct3DDevice9Ex. You can read about sharing resources here.
Now the problem is that directshow seems to be giving problem after a few hours of playback, either due to the codec, video driver or video file itself. At which point the application simply refuse playing anymore video.
Why not just fix this bug instead?
If you separate it out as a separate process then I suspect this would not be possible, but if it were a child thread then they would have shared memory addressing I believe.
Passing textures doesn't work.
I'd do it using the following methods:
Replace the VMR with a custom renderer+allocator that places the picture into memory
You allocate memory for pictures from a shared memory pool
Once you receive another picture you signal an event
The Direct3D process waits for this event and updates the mesh with the new texture
Note you'll need to transfer the picture data to the graphics card. The big difference is that this transfer now happens in the Direct3D app and not in the DirectShow app.
You could also try to use the VMR for this. I'm not sure if the custom allocator/renderer parts will allow you to render into shared memory.
Maybe you could use the Sample Grabber in your DirectShow host process to get the image as a system memory buffer. Then you could use WriteProcessMemory to write the data into a pre-agreed address (which you setup over TCP or something) in your Direct3D app.

Categories

Resources