NAudio 1.7 MediaFoundationEncoder - naudio

I have a problem with MediaFoundationEncoder
I need to record from input device file in AAC format, I write the following code:
private Timer timer;
private static IWaveIn _waveIn;
private static IWaveProvider _provider;
public void StartRecorder()
{
_waveIn = new WaveInEvent
{
WaveFormat = new WaveFormat(8000, 1)
};
_provider = new WaveInProvider(_waveIn);
_waveIn.DataAvailable += OnDataAvailable;
_waveIn.StartRecording();
//for testing purpose write only first 5 seconds.
timer = new Timer(5000);
timer.Elapsed += (sender, args) => Stop();
timer.Start();
}
private void Stop()
{
timer.Stop();
_waveIn.StopRecording();
_waveIn.Dispose();
_waveIn = null;
var outputFilename = String.Format("D:\\{0:yyy-mm-dd HH-mm-ss}.aac", DateTime.Now);
MediaFoundationEncoder.EncodeToAac(_provider, outputFilename);
_provider = null;
}
Also I tried to use MediaFoundationEncoder.EncodeToWma - BUT the file size continued to grow even after stopping the recording and disposed _waveIn. Timeline in file is corrrect, something writes to file trash bytes.
P.S. Im using the lastet build of NAudio (1.7).

The file size growing indefinitely issue is likely because your input provider never returns 0 from its Read method. I'd recommend you write all your audio to a memory stream and then use that with a RawSourceWaveProvider to form the input to your encoder. (remember to set the MemoryStream position to 0 before encoding)

Related

EPPlus - Saving to Memory Stream results in empty file, Saving to File works ok

I have what appears to be a strange problem with C# that I've not been able to figure out, hoping for some help here.
I've written the below demo that creates what is essentially the same file, but one Saves the ExcelPackage to a file using ExcelPackage.SaveAs(FileInfo(filePath)) (which works just fine and as expected), while the other saves to a MemoryStream (which results in a completely empty file).
Interestingly I do have other applications that utilise the same MemoryStream pattern and the file saves just fine, but it seems "temperamental" and can't figure out when it works and when it does not.
Anyone knows why this happens and how I can get it to work via a MemoryStream?
class Program
{
static void Main(string[] args)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
TestXLToFile($#"Export\Test-{DateTime.Now.ToString("dd-MM-yy.H.mm.ss")}.xlsx");
var stream = TestXLToMemStream();
stream.CopyTo(new FileStream($#"Export\TestMs-{DateTime.Now.ToString("dd-MM-yy.H.mm.ss")}.xlsx", FileMode.Create));
}
public static void TestXLToFile(string FilePath)
{
using (ExcelPackage xl = new ExcelPackage())
{
var ws = xl.Workbook.Worksheets.Add("TEST");
ws.Cells[1, 1].Value = "abc123";
xl.SaveAs(new FileInfo(FilePath));
}
}
public static MemoryStream TestXLToMemStream()
{
ExcelPackage xl = new ExcelPackage();
var ws = xl.Workbook.Worksheets.Add("TEST");
ws.Cells[1, 1].Value = "abc123";
MemoryStream ms = new MemoryStream();
xl.SaveAs(ms);
return ms;
}
}
The problem is because you are not calling the Flush and Close methods for the FileStream. You should make use of the Using statement when using Streams as follows:
using(var stream = TestXLToMemStream())
using(var fileStream = new FileStream($#"Export\TestMS-{DateTime.Now.ToString("dd-MM-yy.H.mm.ss")}.xlsx", FileMode.Create, FileAccess.Write))
{
stream.WriteTo(fileStream);
}

How to set image.Source via async stream in an UWP application?

I want to set image.Source via async stream in an UWP application. Otherwise the image will flicker when switch to other image source.
My code is as below. And the log shows it works. Certainly I put 2 image files in the corresponding path before I test the demo code.
But in fact I did not see any picture shown, why?
Log:
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\2.jpg
22222222222
33333333333333
4444444444444
The thread 0x6d38 has exited with code 0 (0x0).
The thread 0x6a34 has exited with code 0 (0x0).
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\1.jpg
22222222222
33333333333333
4444444444444
Code:
private async void setImageSource(string imageFilePath)
{
StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
Debug.WriteLine("111111111111 image file path = " + imageFilePath);
Stream fileStream = await sFile.OpenStreamForReadAsync();
Debug.WriteLine("22222222222");
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
Debug.WriteLine("33333333333333");
await fileStream.CopyToAsync(ras.AsStreamForRead());
Debug.WriteLine("4444444444444");
BitmapImage bi = new BitmapImage();
bi.SetSource(ras);
image1.Source = bi;
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
string fullFolder = ApplicationData.Current.LocalFolder.Path;
if (count % 2 == 1)
{
setImageSource(fullFolder + #"\1.jpg");
//image1.Source = new BitmapImage(new Uri(#"ms-appx:///Assets/1.jpg"));
}
else
{
setImageSource(fullFolder + #"\2.jpg");
//image1.Source = new BitmapImage(new Uri(#"ms-appx:///Assets/2.jpg"));
}
count++;
}
Here is an example of how I convert a base64 image string to a BitmapImage..
var ims = new InMemoryRandomAccessStream();
var bytes = Convert.FromBase64String(base64String);
var dataWriter = new DataWriter(ims);
dataWriter.WriteBytes(bytes);
await dataWriter.StoreAsync();
ims.Seek(0);
var img = new BitmapImage();
img.SetSource(ims);
ims.Dispose();
return img;
Try some of the things I'm doing there. Like I notice your code is not setting the seek of the InMemoryReadAccessStream
For your question, I have something to clarify with you.
Your pictures are always in the application data folder. If you want to show it at runtime by programming, the easy way is using the ms-appdata URI scheme to refer to files that come from the app's local, roaming, and temporary data folders. Then, you could use this URL to initialize the BitmapImage object. With this way, you don't need to manually manipulate the file stream.
private void setImageSource(int i)
{
BitmapImage bi = new BitmapImage(new Uri("ms-appdata:///local/"+i+".png"));
image1.Source = bi;
}
private int count = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (count % 2 == 1)
{
setImageSource(1);
}
else
{
setImageSource(2);
}
count++;
}
If you say you have to manipulate the file stream to initialize the BitmaImage, then please add some break points to debug your code. If you add break points to check the InMemoryRandomAccessStream after call CopyToAsync method, you will see that its size is 0. It meant that the file stream has not been wrote to it. To solve this issue, you need to set a buffer size for it. Note: you used ras.AsStreamForRead() method, it's incorrect. You're writing stream to it, so you need to call ras.AsStreamForWrite().
The code looks like the following:
private async void setImageSource(string imageFilePath)
{
StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
using (Stream fileStream = await sFile.OpenStreamForReadAsync())
{
using (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream())
{
await fileStream.CopyToAsync(ras.AsStreamForWrite((int)fileStream.Length));
ras.Seek(0);
BitmapImage bi = new BitmapImage();
bi.SetSource(ras);
img.Source = bi;
}
}
}
private int count = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
string fullFolder = ApplicationData.Current.LocalFolder.Path;
if (count % 2 == 1)
{
setImageSource(fullFolder + #"\1.jpg");
}
else
{
setImageSource(fullFolder + #"\2.jpg");
}
count++;
}
In addition, like #visc said, you need to call ras.Seek(0) method to reset the stream to beginning, else the image will not show there.

Uploading byte array to MYSQL shows empty field (nothing uploaded?)

I've been trying to write a script which opens a file with UniFileViewer, sets a path to the file and passes it to various methods which serialize it and upload it to my MYSQL server. When I run the script it executes without problems but the result is 0 bytes uploaded to the database. I must have missed something here...
public class FileOpen : MonoBehaviour
{
public UITexture ProfilePic;
public static Texture2D tex = null;
public static String selectedFilePath;
void openFile()
{
UniFileBrowser.use.OpenFileWindow(OpenFile);
}
public static Texture2D LoadPNG(string selectedFilePath)
{
byte[] fileData;
fileData = File.ReadAllBytes(selectedFilePath);
tex = new Texture2D(2, 2);
tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
return tex;
}
//OPENS THE FILE AND SENDS IT TO THE SERVER
void OpenFile(string filePath)
{
selectedFilePath = filePath;
LoadPNG(selectedFilePath);
Texture2D uploadFile = tex;
byte[] bytes = uploadFile.EncodeToPNG();
string fileToSend = Convert.ToBase64String(bytes);
string[] datas = new string[1];
datas[0] = fileToSend;
LoginPro.Manager.ExecuteOnServer("SaveFile", SendToServer_Success, SendToServer_Error, datas);
}

Apache Tika - read chunk at a time from a file?

Is there any way to read chunk at a time (instead of reading the entire file) from a file using Tika API?
following is my code. As you can see I am reading the entire file at once. I would like to read chunk at a time and create a text file the content.
InputStream stream = new FileInputStream(file);
Parser p = new AutoDetectParser();
Metadata meta =new Metadata();
WriteOutContentHandler handler = new WriteOutContnetHandler(-1);
ParseContext parse = new ParseContext();
....
p.parse(stream,handler,meta, context);
...
String content = handler.toString();
There's (now) and Apache Tika example which shows how you can capture the plain text output, and return it in chunks based on the maximum allowed size of a chunk. You can find it in ContentHandlerExample - method is parseToPlainTextChunks
Based on that, if you wanted to output to a file instead, and on a per-chunk basis, you'd tweak it to be something like:
final int MAXIMUM_TEXT_CHUNK_SIZE = 100 * 1024 * 1024;
final File outputDir = new File("/tmp/");
private class ChunkHandler extends ContentHandlerDecorator {
private int size = 0;
private int fileNumber = -1;
private OutputStreamWriter out = null;
#Override
public void characters(char[] ch, int start, int length) throws IOException {
if (out == null || size+length > MAXIMUM_TEXT_CHUNK_SIZE) {
if (out != null) out.close();
fileNumber++;
File f = new File(outputDir, "output-" + fileNumber + ".txt);
out = new OutputStreamWriter(new FileOutputStream(f, "UTF-8"));
}
out.write(ch, start, length);
}
public void close() throws IOException {
if (out != null) out.close();
}
}
public void parse(File file) {
InputStream stream = new FileInputStream(file);
Parser p = new AutoDetectParser();
Metadata meta =new Metadata();
ContentHandler handler = new ChunkHandler();
ParseContext parse = new ParseContext();
p.parse(stream,handler,meta, context);
((ChunkHandler)handler).close();
}
That will give you plain text files in the given directory, of no more than a maximum size. All html tags will be ignored, you'll only get the plain textual content

webClient.DownloadString load new string

it's my code:
public void pobierzSuchary()
{
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri("http://../michal/suchary.txt"));
}
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
ToastPrompt toast = new ToastPrompt
{
Background = new SolidColorBrush(Colors.Green),
Message = "Suchary zostaƂy pobrane"
};
String[] sucharyTab = e.Result.Split('#');
MessageBox.Show(sucharyTab[1]);
..
}
Button runs pobierzSuchary() and is downloading string, I have a problem when I press second time button. Then i see in messagebox older value, but i changed string on server(manually). I have to disable the applications and run again to see new string
This happens because the windows phone automatically caches values for repeat calls.
Just append a random number onto the end of your webclient call
Something like this
Random ran = new Random();
webClient.DownloadStringAsync(new Uri("http://../michal/suchary.txt?ran="+ran.next().toString()));