Record to a MemoryStream using NAudio - c#

I'm trying to use NAudio to record from the micrphone and save tthat data to a MemoryStream. There doesn't seem to be an obvious way and everytime I try to read from my BufferedWaveProvider, the recording no longer plays when using WaveOut.Play. It recording plays fine if I remove my read attempt. Is there a way to record to a MemoryStream?
This is how I've tried to convert it to a MemoryStream:
Byte[] stream = new byte[bwp.BufferedBytes];
bwp.Read(stream, 0, bwp.BufferedBytes);
wo.Play(); //plays fine only if I comment out the Read line above
MemoryStream ms = new MemoryStream(stream);

A WaveProvider can only have one consumer of its Read method. I suggest that at the point you add bytes to your BufferedWaveProvider you also add them to your memory stream. The alternative is to inherit from IWaveProvider, and in the Read method, read from the BufferedWaveProvider and write what you read to the MemoryStream before returning. Then use that WaveProvider to give to WaveOut.

There is a link out on code project along with the source code that you can download to help you to do what you are trying.
There is an example project on codeproject doing this:
http://www.codeproject.com/KB/cs/Streaming_wave_audio.aspx
I don't know how low the latency is.
As a codec I'd recommend Speex(at least for speech). It's free, open source and offers low latency and low bandwidth.

Related

Can't Use Stream.Write method while playing same file in MediaElement

So lets say I have a file which has around 2MB already downloaded and written which is being played using a MediaElement. So while the media is being played, I want to download and write the rest of the file.
If I use this method, I get an IOExecption error indicating the file is already in use.
using (Stream WriteStream = new FileStream(filename, FileMode.OpenOrCreate))
{
WriteStream.Seek(seekpos, SeekOrigin.Begin);
WriteStream.Write(buffer, 0, buffer.Length);
WriteStream.Close();
}
But if I use this method, it works fine.
FileStream1 = new System.IO.FileStream(filename, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
FileStream1.Write(buffer, 0, buffer.Length);
So I could use the second method, but I want to be able to seek and write at certain positions which I can't do using the second method. So is there anyway in which I can use the first method. Does it have something to do with the FILEMODE or FILEACCESS?
Thanks :)
The closest you might get might be displayed here with what's known as a synchronized stream. Essentially, it's multiple threads acting on the same stream. You'd have to get the locking issue resolved, especially since you may have no way of making the MediaElement open the file with a shared lock.
Another approach might be to write to one file while the MediaElement plays from another. When the MediaElement's done with file A, play B and stream downloads to new file C. Repeat. Then, at the end, merge them together.
Never-mind I figured it out. I can use this to seek and write at any position. Stupid of me to not realise this.
FileStream1 = new System.IO.FileStream(filename, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
FileStream1.Seek(seekpos,SeekOrigin.Begin);
FileStream1.Write(buffer, 0, buffer.Length);

Read Second audio track stream from mp4 file using SharpDx or IMSourceReader

I have a requirement in my application where I have to read all the available track stream from mp4 file.
Mp4 file is encoded with number of tracks in AAC format. I have to decode to get all available tracks from the file. Currently I am using SharpDX and IMSourceReader (Media Foundation dlls) to read the Streams. But by default SourceReader returns only the first audio stream from the file. Is it I am doing correct ? Or I have to use any other third party libraries to achieve this ?
When configuring the reader, you can select which streams will be delivered when reading samples. Often times you do not wish to select the stream. An example would be a movie which has additional audio streams (spanish, french, or perhaps director commentary). As a result, most of the time stream selection is as simple as the following:
// error checking omitted for brevity
hr = reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, nullptr, audioMediaType);
hr = reader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
However if you look at SetStreamSelection, the first parameter takes either the enumeration used above, or a specific stream index.
// 0–0xFFFFFFFB <-- The zero-based index of a stream.
// 0xFFFFFFFC <-- MF_SOURCE_READER_FIRST_VIDEO_STREAM
// 0xFFFFFFFD <-- MF_SOURCE_READER_FIRST_AUDIO_STREAM
// 0xFFFFFFFE <-- MF_SOURCE_READER_ALL_STREAMS
// 0xFFFFFFFE <-- MF_SOURCE_READER_ANY_STREAM
// 0xFFFFFFFF <-- MF_SOURCE_READER_INVALID_STREAM_INDEX
I have never used SharpDX, but this enumeration is documented here.
Pertaining to video, sometimes additional video streams are available (usually closed captioning).
When reading the samples, using a callback or synchronously, pay close attention to the stream index, and process the sample accordingly.
You may also find these answers valuable or interesting:
Aggregate Media Source
MP4 IMFSinkWriter
Adding Audio Sample to Video
Creating NV12 Encoded Video
IMFSinkWriter Configuration
IMFSinkWriter CPU Utilization
I hope this helps.

send array of bytes to System.Media.SoundPlayer in c#

I want send string byte to speaker something like this:
byte[] bt = {12,32,43,74,23,53,24,54,234,253,153};// example array
var ms = new MemoryStream(bt);
var sound = new System.Media.SoundPlayer();
sound.Stream = ms;
sound.Play();
but I get this exception:
my problem pic http://8pic.ir/images/g699b52xe5ap9s8yf0pz.jpg
The first bytes of a WAV stream contain info about length, etc.
You have to send this "WAV-Header" as well in the first few bytes.
See http://de.wikipedia.org/wiki/RIFF_WAVE
As you'll see its perfectly possible to compose these few bytes in the header and send them before your raw audio data,
You can use some library for reading data from microphone or playing it to speakers.
I worked successfuly with:
NAudio - http://naudio.codeplex.com/
I would not recommend building a WAV file yourself, it may be too much effort for this.
Note that this library (and probably some others, Bass - http://www.un4seen.com is also widely used) also have built in functionality for saving and reading WAV files.
NAudio is best app to play that functionality. use sample app provided.It may help.

C# Video Streaming

I'm trying to do a application with video stream, and by now I can send only one image from the server to the client. When I try to send more than only one image at the client I receive the following error: "Parameter is not valid." at pictureBox1.Image = new Bitmap(ms);
Client side code:
while((data = cliente.receiveImage()) != null)
{
ms = new MemoryStream(data);
pictureBox1.Image = new Bitmap(ms);
ms.Close();
}
Server side code (this code is repeated continuously):
servidor.sendImage(ms.GetBuffer());
ms.GetBuffer() returns the entire buffer of the memory stream, including any extra unused portion.
You should call ToArray(), which only returns actual contents.
(Or, your data might be invalid for some other reason, such as an issue in sendImage or receiveImage)
Images are nit-picky things, and you have to have the entire set of bytes that comprise the image in order to reconstruct an image.
I would bet my left shoe that the issue is that when the client object is receiving data, it's getting it in chunks comprised of partial images, not the whole image at once. This would cause the line that says
pictureBox1.Image = new Bitmap(ms);
to fail because it simply doesn't have a whole image's bytes.
Alternatives
Rather than having the server push images out to the client, perhaps another approach would be to have the client pull images from the server.
Use an existing streaming mechanism. I personally think that streaming video manually from C# may be more complex than you're bargaining for, and I'd humbly recommend using an existing component or application to stream the video rather than writing your own. There are already so many different options out there (wmv, Flash, and a hundred more) that you're reinventing a wheel that really doesn't need to be re-invented.

C# - How to use Jpeg to compress images and send to a server?

I want to build a Screen Sharing program in C#.(with TCP)
I sniffed around the web and found out that the most efficient way to do it is by sending alot of screenshots from the client to the server.
The point is - how can I compress a Bitmap to Jpeg - receive it on the server and decompress again to Bitmap (so I can show it in a form) ?
I've tried using the JpegBitmapEncoder with no luck, here's my code:
Bitmap screen = TakeScreenshot();
MemoryStream ms = new MemoryStream();
byte[] Bytes = BmpToBytes_Unsafe(screen);
ms.Write(Bytes, 0, Bytes.Length);
Jpeg = new JpegBitmapEncoder();
Jpeg.Frames.Add(BitmapFrame.Create(ms));
Jpeg.QualityLevel = 40;
Jpeg.Save(ms);
BinaryReader br = new BinaryReader(ms);
SendMessage(br.ReadBytes((int)ms.Length));
It throws an NotSupportedException at Jpeg.Frames.Add(BitmapFrame.Create(ms));
No imaging component suitable to complete this operation was found.
So I need a way to convert a Bitmap to Jpeg, then to byte[], then send it over TCP.
And on the other end, do the exact opposite. Any suggestions ?
Thank you.
JPEG was designed for photographs, not for screen captures. Also, most of the screen doesn't change so better to just send the changed portions and only a full screen when much of the screen has changed.
Unless you're just doing this for fun, you are going about this all wrong. VNC has been doing this for years and the source code is free so you could look to see how that's done.

Categories