CSCore - Play audio from MemoryStream - memorystream

I am new to CsCore. Need some help. I want to build an Audio Recorder, which is able to record mic and Speakers into a file and an external Recorder device. I have successfully finished recording to file. Now I want just the same thing once again, but playing on a certain audio speaker device. I thought of piping into a stream and using this stream as source for a WasapiOut. However, I failed connecting this stream to an IWaveSource.
private Stream _strm;
private WaveWriter _waveWriterFile;
private WaveWriter _wavewriterStream;
private WasapiOut _externalRecorder;
_strm = new MemoryStream();
_wavewriterStream = new WaveWriter(_strm, _SpkCapture.WaveFormat);
IWaveSource ws = new WaveFileReader(_strm);
_externalRecorder.Initialize(ws);
_externalRecorder.Play();
// on Event I do following:
_waveWriterFile.Write(e.Data, e.Offset, e.ByteCount);
_wavewriterStream.Write(e.Data, e.Offset, e.ByteCount);
Everything works fine until I call 'new WaveFileReader(_strm);'. I get an exception (translated from me) "cannot read beyond end of stream". The stream contains data at this point of time. Have 100ms sleep before trying to fetch the stream. I have also tried
IWaveSource ws = new CSCore.MediaFoundation.MediaFoundationDecoder(strm);
But no luck. I really need help.

Related

Uploading an image to a site via their API

I have a bot running in an online game which the staff use to draw out the map's levels. It uploads these pics to Imgur using its API, but Imgur isn't always up and running so I'd like to add a 2nd host as a backup plan.
I discovered this site which looks like a fine choice: https://boring.host/api
To get an API key, sign up (fast, no confirmation needed) then go to "My Account" by clicking your name on the top right.
Looking at the API info, it looks like I just need to send a HTTP POST to "https://api.boring.host/api/v1/upload" and include the "api_token" and "file" parameters.
When I upload to Imgur, I write the image to a MemoryStream then convert that to a Base64String:
Convert.ToBase64String(bytImage)
So I tried the same thing for this:
Public Function UploadBoringHost(Dim bm as Bitmap) As String
'Write image to memorystream
Dim bytImage As Byte()
Using stream As New System.IO.MemoryStream
bm.Save(stream, System.Drawing.Imaging.ImageFormat.Png)
bytImage = stream.ToArray
End Using
'Upload
Using client As New WebClient
Dim reqparm As New Specialized.NameValueCollection
reqparm.Add("api_token", strApiKey)
reqparm.Add("file", Convert.ToBase64String(bytImage))
Dim responsebytes = client.UploadValues("https://api.boring.host/api/v1/upload", "POST", reqparm)
Dim responsebody = (New Text.UTF8Encoding).GetString(responsebytes)
End Using
End Function
Trying it this way, I get the following web exception: "The remote server returned an error: (422) Unprocessable Entity"
My only guess is that it's expecting the image data to be passed through in some other format. Any ideas?

Ignore user input while Uploading to FTP

I'm developing a windows store app, and I'm uploading a file to an FTP server with WebRequest, since it was the only work around I could find, with the limitations that I had.
When the application is uploading the video, which takes a few minutes, if the user taps the screen the app will crash. If no input is made, it will work fine.
When I was using Alex Pilotti's FTPS Client DLL, this didn't happen, but I couldn't get the certification for windows store using this DLL.
In my PC, this doesn't happen. It will wait until the video is uploaded and then execute the user input, but in the tablet it's a different story, maybe because it has less processing power/memory, it just crashes.
I was thinking: maybe there is a way to ignore all user input while the upload is happening.
I know it's not the best way, to take control from the user like that, but it would do the job and it would only be for a few minutes.
I've been googling, but I can't find a way to do this.
I'll leave my code below, just in case:
Public Async Function uploadFile(filename As String, file As StorageFile) As Task(Of Boolean)
Try
Dim ftpURL As String = "ftp://111.22.33.444"
Dim request As WebRequest = WebRequest.Create(ftpURL + "/" + filename)
request.Credentials = New NetworkCredential("user", "pass")
request.Method = "STOR"
Dim buffer As Byte() = Await ReadFileToBinary(filename, file)
Dim requestStream As Stream = Await request.GetRequestStreamAsync()
Await requestStream.WriteAsync(buffer, 0, buffer.Length)
Await requestStream.FlushAsync()
Return True
Catch ex As Exception
Return False
End Try
End Function
I fixed this issue with a very simple line of code:
Await Task.Run(Function() uploadFile(filename, file))
Worked for me.

Winrt StreamWriter & StorageFile does not completely Overwrite File

Quick search here yielded nothing. So, I have started using some rather roundabout ways to use StreamWriter in my WinRT Application. Reading works well, writing works differently. What' I'm seeing is that when I select my file to write, if I choose a new file then no problem. The file is created as I expect. If I choose to overwrite a file, then the file is overwritten to a point, but the point where the stream stops writing, if the original file was large, then the old contents exist past where my new stream writes.
The code is as such:
public async void WriteFile(StorageFile selectedFileToSave)
{
// At this point, selectedFileToSave is from the Save File picker so can be a enw or existing file
StreamWriter writeStream;
Encoding enc = new UTF8Encoding();
Stream dotNetStream;
dotNetStream = await selectedFileToSave.OpenStreamForWriteAsync();
StreamWriter writeStream = new StreamWriter(dotNetStream, enc);
// Do writing here
// Close
writeStream.Write(Environment.NewLine);
await writeStream.FlushAsync();
await dotNetStream.FlushAsync();
}
Can anyone offer clues on what I could be missing? There are lots of functions missing in WinRT, so not really following ways to get around this
Alternatively you can set length of the stream to 0 with SetLength method before using StreamWriter:
var stream = await file.OpenStreamForWriteAsync();
stream.SetLength(0);
using (var writer = new StreamWriter(stream))
{
writer.Write(text);
}
Why not just use the helper methods in FileIO class? You could call:
FileIO.WriteTextAsync(selectedFileToSave, newTextContents);
If you really need a StreamWriter, first truncate the file by calling
FileIO.WriteBytesAsync(selectedFileToSave, new byte[0]);
And then continue with your existing code.

Stream text to client via handler ASP.NET

To get around twitters streaming API not having a crossdomain file to access it from client side( in this case Silverlight) I have made a Generic Handler file in a web project which basically downloads the stream from twitter and as it reads it, writes it to the client.
Here is the handler code:
context.Response.Buffer = false;
context.Response.ContentType = "text/plain";
WebRequest request = WebRequest.Create("http://stream.twitter.com/1/statuses/filter.json?locations=-180,-90,180,90");
request.Credentials = new NetworkCredential("username", "password");
StreamReader responseStream = new StreamReader(request.GetResponse().GetResponseStream(), Encoding.GetEncoding("utf-8"));
while (!responseStream.EndOfStream)
{
string line = "(~!-/" + responseStream.ReadLine() + "~!-/)";
context.Response.BinaryWrite((Encoding.UTF8.GetBytes(line)));}
And this does work, but the problem is that once the client disconnects the handler just carry's on downloading. So how do I tell if the client is still busy receiving the request and if not, end the while loop?
Also, my second problem is that on the client side doing a "ReadLine()" does nothing, presumably because it is counting the entire stream as one line so never gets the full response. To work around that I read it byte by byte and when it sees "(~!-/" around something it know that is one line. VERY hacky, I know.
Thanks!
Found the answer!
while (context.Response.IsClientConnected)
:)

HttpWebRequest for ShoutCast on Windows Phone7

I tring to stream shoutcast stream in my window phone 7 app
I start an async HttpWebRequest like this
//Init Request
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://ACommonoShoutCastUrl:8000");
myHttpWebRequest.Headers["Icy-MetaData"] = "1";
myHttpWebRequest.UserAgent = "WinampMPEG/5.09";
myHttpWebRequest.AllowReadStreamBuffering = true;
//Call
// Create an instance of the RequestState and assign the previous myHttpWebRequest object to its request field.
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;
// Start the asynchronous request.
IAsyncResult result = (IAsyncResult)myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallBack), myRequestState);
The problem is that the CallBack->RespCallBack is never called...
This code worked for me normally in other environments but not on the phone...
I tired also to use WebClient that seems to stream data,
the problem in this case is that it never call the end OpenReadCompleted because of endelss shoutcast stream
Thanks for support
any help would be appreciated
SHOUTcast implements its own protocol so you can't directly access and play it. You can use DownloadStringAsync (you will need a WebClient instance for this) to download the PLS file and read the URL with the help of RegEx.
When you get the URL, you can read the raw audio data by implementing MediaStreamSource and then use a MediaElement to play the contents.
You can find a sample implementation of MediaStreamSource here.
I just put the following on a page and the callback was called in repsonse to the button click. (I set a break point on the throw statement and it was hit.)
private HttpWebRequest myHttpWebRequest;
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//Init Request
//The following URI was chosen at random
myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://yp.shoutcast.com/sbin/tunein-station.pls?id=1377200");
myHttpWebRequest.Headers["Icy-MetaData"] = "1";
myHttpWebRequest.UserAgent = "WinampMPEG/5.09";
myHttpWebRequest.AllowReadStreamBuffering = true;
// Start the asynchronous request.
myHttpWebRequest.BeginGetResponse(RespCallBack, myHttpWebRequest);
}
private void RespCallBack(IAsyncResult ar)
{
throw new NotImplementedException();
}
I am trying to implement the Shoutcast streaming to my MediaElement via my own MediaStreamSource class. I have a loop in which I am downloading data from Shoutcast server and then set the data to the MediaStreamSource class - this works not perfectly for yet, but I discovered another more important issue. I made a test. I have downloaded a stream to a mp3 (stream is in mp3) file, then put this file to my application and set it to my MediaStreamSource. Here's the code for this:
private void Button_Click(object sender, RoutedEventArgs e)
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
var res = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("Demo1.sample.mp3");
byte[] data = new byte[res.Length];
res.Read(data, 0, data.Length);
MemoryStream ms = new MemoryStream();
ms.Write(data, 0, data.Length);
ms.Position = 0;
ShoutcastMediaStreamSource ss = new ShoutcastMediaStreamSource(ms);
player.SetSource(ss);
}
my ShoutcastMediaStreamSource based on MenagedMediaHelpers. So when I put this stream to my ShoutcastMediaStreamSource in debbuger I can see that the method OpenMediaAsync() is called properly, then the GetSampleAsync() is called in a loop by MediaElement, here also everything is fine, but when I run this app there is no sound ! Neither on the emulator nor on the device, and there are no errors. I think, the GetSampleAsync() method is running too fast, bacause for the file (and also stream) duration is about 30 sec., and this app ends after ca. 10 sec. But nevertheless, there should be a sound (scratch).
BUT whats suprising - this app works in Silverlight as Web Page ! The music is playing. I am confused.
Here is allso an app
http://timheuer.com/blog/archive/2010/08/16/download-and-store-media-for-playback-in-windows-phone-7-using-mediastreamsource.aspx
and there is a comment:
If Mp3MediaStreamSource is set as a
source for MediaElement then
MediaElement doesn't play that file
and donesn't show any error in Windows
phone 7 sdk RTM version. In previsios
version it was working but it's not
working with Windows phone 7 sdk final
release.
The callback gets called if you disable read stream buffering:
webRequest.AllowReadStreamBuffering = false;