Problem / Error with converting M4A Audio File to MP3 using NAudio in C# - c#

I'm in a process of creating a demo for an audio conversion software that I create as a hobby. I wanted converting an M4A (MPEG-4) audio file to an MP3 using a simple GUI for the user to interact. I also implemented a feature that allows the user to play the selected audio file (M4A) before conversion, which I have learned from watching NAudio video tutorials. However, I was stuck with a specific issue that stops me from progressing this demo project.
I have received an error right after the SaveFileDialogue selection to place the converted file (MP3) which prevents me from continuing the process. (I have put the error message in the comments for all of you to see in the method of btnConvertToMp3_Click()).
I have tried using MediaFoundationEncoder.EncodeToMp3() to solve this case. Unfortunately, I get an error, stating that there are "No available MP3 encoders" which I have researched that it is not fully supported enough to be used functionally for every audio format.
I have tried searching for more solutions, close to this problem but sadly could not find what I was hoping for, so I decided to ask if you have any input about this problem.
Here is my current code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NAudio.Wave;
using NAudio;
using NAudio.Lame;
using NAudio.Dmo;
using System.Windows.Forms;
namespace M4AtoMP3ConversionDEMO
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private NAudio.Wave.BlockAlignReductionStream stream = null;
private NAudio.Wave.DirectSoundOut output = null;
public void btnOpenM4AFile_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.Filter = "M4A Audio File (*.m4a)|*.m4a;";
if (open.ShowDialog() != DialogResult.OK)
{
return;
}
MediaFoundationReader mfM4A = new MediaFoundationReader(open.FileName);
stream = new NAudio.Wave.BlockAlignReductionStream(mfM4A);
btnPlayPauseButton.Enabled = true;
btnConvertToMP3.Visible = true;
output = new NAudio.Wave.DirectSoundOut();
output.Init(mfM4A);
output.Play();
MessageBox.Show(".M4A Format has been accepted", ".M4A Audio Format", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void btnConvertToMP3_Click(object sender, EventArgs e)
{
DialogResult mb1 = MessageBox.Show("Are you sure you want to convert this M4A File?", "Converting to MP3", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
switch (mb1)
{
case DialogResult.Yes:
SaveFileDialog save = new SaveFileDialog();
save.Filter = "MP3 File (*.mp3)|*.mp3";
if (save.ShowDialog() != DialogResult.OK) return;
// Unable to cast COM object of type 'System.__ComObject' to interface type 'NAudio.MediaFoundation.IMFSourceReader'.
// This operation failed because the QueryInterface call on the COM component for the interface with IID '{70AE66F2-C809-4E4F-8915-BDCB406B7993}' failed due to the following error:
// No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))
using (var mp3FileReader = new LameMP3FileWriter(save.FileName, stream.WaveFormat, LAMEPreset.ABR_320))
{
stream.CopyTo(mp3FileReader);
}
break;
case DialogResult.No:
break;
}
}
private void btnPlayPauseButton_Click(object sender, EventArgs e)
{
if (output != null)
{
if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing)
{
output.Pause();
Image playButton = new Bitmap(#"C:\Users\CeX\source\repos\AudioConverterUI-WorkInProgress\AudioConverterUI-WorkInProgress\Resources\play-button-size.png");
btnPlayPauseButton.Image = playButton;
}
else if (output.PlaybackState == NAudio.Wave.PlaybackState.Paused)
{
output.Play();
Image pauseButton = new Bitmap(#"C:\Users\CeX\source\repos\AudioConverterUI-WorkInProgress\AudioConverterUI-WorkInProgress\Resources\pause-button-size.png");
btnPlayPauseButton.Image = pauseButton;
}
}
}
private void DisposeWave()
{
if (output != null)
{
if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing)
{
output.Stop();
output.Dispose();
output = null;
}
if (stream != null)
{
stream.Dispose();
stream = null;
}
}
}
}
}
If there isn't a suitable solution to this error, is there a possible alternative or simple solution that would allow me to convert M4A to MP3 without using NAudio, even with GUI?

A simple approach without using NAudio (which relies on Windows codecs) is to use FFMPEG, and do a command line conversion.

Related

UWP SharpCompress Access Exception On Local Drives, Why?

I'm trying to use SharpCompress to read .rar files from my UWP application. It works fine on network shares from which I can read the archive no problem, but I get System.UnauthorizedAccessException on files anywhere on the local system including for instance USB drives. I have access to the files by other methods e.g. StorageFile. It makes no difference whether BroadFileSystemAccess is on or off. I've tried in both C# and Vb.net Here's the code of my test app in C#. The exception occurs at ArchiveFactory.Open.
I can also read Zip files no problem using the .net Compression methods but they can't do rar files, hence needing SharpCompress.
using System;
using System.IO;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using SharpCompress;
using Windows.Storage.Pickers;
using Windows.Storage;
using SharpCompress.Archives;
namespace TestRAR
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
OpenRAR.Click += OpenRAR_Clicked;
}
public async void OpenRAR_Clicked(object sender, RoutedEventArgs e)
{
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".rar");
picker.FileTypeFilter.Add(".cbr");
picker.FileTypeFilter.Add(".cbz");
picker.FileTypeFilter.Add(".zip");
StorageFile pickfile = await picker.PickSingleFileAsync();
if (pickfile == null) { return; }
string pth = pickfile.Path;
FileInfo pickInfo = new FileInfo(pth);
try
{
ListRARs.Items.Clear();
using (var Arch = ArchiveFactory.Open(pickInfo))
{
foreach (IArchiveEntry a in Arch.Entries)
{
string thisKey = a.Key;
ListRARs.Items.Add(thisKey);
}
}
}
catch{ }
}
}
}
This is the first time I've used SharpCompress and I'm completely stumped. Any ideas anyone?

Webclient.DownloadFileCompleted event failed

I am downloading a large file from a web site.
Size: = 599 MB (629,113,799 bytes).
The program works fine.
However I run into some errors:
not able to validate that the file was completely donwloaded.
I did not see any of the messages in the screen that says
Console.WriteLine("..............File succesfully downloaded......This mesage comes from -- wc_DownloadFileCompleted..........");
So the program does download the file completely.
(I did download the file manually using the web browser and compared the
file size between the manual download and the file that was downloaded
via the program. The size was the same. So that is a good reason for me
to believe that the program did download the file completely)
However at the very end (after it displays the percentage as 99)
it throws an error.. Here is the message
An exception occured during a WebClient request.
The error message gets fired inside the wc_DownloadFileCompleted
method.
So the help I need is... How do we validate that the file was downloaded
completely (without any errors)? Also how do we eliminate the error.
Is there some other code that I can use instead of using the code
I presented.
I did see the File Download percentage 99 appear in the screen.
However I did not see the "100" appear. Any comments?
using System.Threading.Tasks;
using System;
using System.Data;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Reflection; //Need this to get the DEBUG path
using MHPUtil;
using System.Net;
using System.Globalization;
namespace CmsNpiFileLoad
{
public static class FileDownLoadPercentage
{
//We need a global variable that will remain the same throughout the run.
//The unique value for this variable will get set in the DownloadFile() method.
public static string Value { get; set; }
}
class CMsNPIFileDownLoad
{
//599 MB (629,113,799 bytes) is the size of the file.
public void DownloadCMSNPIFile()
{
string Destinationfile = "S:\\MIS\\Provider NPI file\\" + "NPI.zip";
string CmsDownLoadSite = "http://download.cms.gov/nppes/NPPES_Data_Dissemination_January_2018.zip";
//Is the INTERNET AVAILABLE
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
Console.WriteLine("Internet available, proceed with the download");
}
else
{
Console.WriteLine("Internet not available, proceed with the download");
return;
}
//So at this point we dont have that file with us locally.. so lets download
Console.WriteLine("Start Downloading....");
try
{
using (WebClient client = new WebClient())
{
client.DownloadProgressChanged += wc_DownloadProgressChanged; // This works well
client.DownloadFileCompleted += wc_DownloadFileCompleted;
client.DownloadFileAsync(new System.Uri(CmsDownLoadSite), Destinationfile);
}
}
catch (WebException we)
{
Console.WriteLine(we.ToString());
}
Console.ReadLine(); // We dont want the black screen to just disapper from us. so we put a readline so that it will keep displaying all the messsages
}
private static void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Cancelled)
{
Console.WriteLine("The download has been cancelled");
return;
}
if (e.Error != null)
{
//I tested the the program 2 times.. each time an error occured.
//The error message is "An exceptipon occured during a WebClient request.
Console.WriteLine("An error ocurred while trying to download file");
Console.WriteLine(e.Error.Message.ToString());
return;
}
// I did not see this on the screen.. ????
Console.WriteLine("..............File succesfully downloaded......This mesage comes from -- wc_DownloadFileCompleted..........");
}
private static void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
if (FileDownLoadPercentage.Value != e.ProgressPercentage.ToString())
{
FileDownLoadPercentage.Value = e.ProgressPercentage.ToString();
//Display File Donwload Percentage ( increments of 10 )
if (Convert.ToInt16(e.ProgressPercentage) % 10 == 0)
Console.WriteLine(e.ProgressPercentage.ToString());
//Show the percentage when it is 99
if (Convert.ToInt16(e.ProgressPercentage) == 99)
Console.WriteLine(e.ProgressPercentage.ToString());
}
if (e.BytesReceived == e.TotalBytesToReceive)
{
Console.WriteLine("File DownLoad Complete...This message comes from -- wc_DownloadProgressChanged "); // I did not see this on the screen.. ????
}
}
}
}

QR Code Scanner in Unity?

I am trying to get QRCode reader in unity that works on ios and Android.
Unity Zxing QR code scanner integration
Using above answer I Have added Vuforia (Working perfectly alone). then i also have added Zxing.unity.dll in plugins folder, then added this script to ARCamera in a scene.
using UnityEngine;
using System;
using System.Collections;
using Vuforia;
using System.Threading;
using ZXing;
using ZXing.QrCode;
using ZXing.Common;
[AddComponentMenu("System/VuforiaScanner")]
public class VuforiaScanner : MonoBehaviour
{
private bool cameraInitialized;
private BarcodeReader barCodeReader;
void Start()
{
barCodeReader = new BarcodeReader();
StartCoroutine(InitializeCamera());
}
private IEnumerator InitializeCamera()
{
// Waiting a little seem to avoid the Vuforia's crashes.
yield return new WaitForSeconds(1.25f);
var isFrameFormatSet = CameraDevice.Instance.SetFrameFormat(Image.PIXEL_FORMAT.RGB888, true);
Debug.Log(String.Format("FormatSet : {0}", isFrameFormatSet));
// Force autofocus.
var isAutoFocus = CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
if (!isAutoFocus)
{
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
Debug.Log(String.Format("AutoFocus : {0}", isAutoFocus));
cameraInitialized = true;
}
private void Update()
{
if (cameraInitialized)
{
try
{
var cameraFeed = CameraDevice.Instance.GetCameraImage(Image.PIXEL_FORMAT.RGB888);
if (cameraFeed == null)
{
return;
}
var data = barCodeReader.Decode(cameraFeed.Pixels, cameraFeed.BufferWidth, cameraFeed.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24);
if (data != null)
{
// QRCode detected.
Debug.Log(data.Text);
}
else
{
Debug.Log("No QR code detected !");
}
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
}
But it is still not detecting any QRCode. Is there any other way to do QRcode reading and writing except Zxing? or any working sample project you have?
I also tried to implement a QRCode Reader with Vuforia and XZing using almost the same code you used. For me it worked, but it took very very long to detect the QRCode.
When I used a Color32 array instead of cameraFeed.pixels it was much quicker:
GUI.DrawTexture(screenRect, webCamTexture, ScaleMode.ScaleToFit);
try
{
IBarcodeReader barcodeReader = new BarcodeReader();
var result = barcodeReader.Decode(webCamTexture.GetPixels32(),
webCamTexture.width, webCamTexture.height);
if (result != null)
{
Debug.Log("DECODED TEXT FROM QR: " + result.Text);
loadNewPoi(Convert.ToInt32(result.Text));
PlayerPrefs.SetInt("camera_enabled", Convert.ToInt32(false));
webCamTexture.Stop();
}
}
But in this example I was using a WebCamTexture instead of Vuforia.
Unluckily it isn't possible to get a Color32 array with GetPixels32() from the Vuforia camera.
Another option is to use the QRCodes as Image-Targets, but I have a lot of wrong detections doing this.
For me there is no fitting solution for XZing together with Vuforia at the moment.

Xamarin/Android - Issue reading locally stored photo from camera - no read access

I'm trying to create a simple test app to take photos in Android, using Xamarin. When I get this app working (or so I hope), i'll use the code in a real app that I'm working on. I'm using the following recipe from Xamarin as my basis:
http://docs.xamarin.com/recipes/android/other_ux/camera_intent/take_a_picture_and_save_using_camera_app/
The major difference is that I need to store images locally, and not on the SD card. I'm able to successfully take a picture (with the Android simulator). I can see the file in the file structure using ADB and can successfully copy and open the file on my PC. However, I'm unsuccessfull in accessing the file in the app, probably due to user rights.
Please note that I was successfull in creating my own .txt files, and reading them back using either System.IO and Java.IO.
Please review the following code. My app crashes when using "System.IO.File.ReadAllText" and gives me "Access to the path "/data/data/CameraAppDemo.CameraAppDemo/files/photo.jpg" is denied.". And whatever I try (absolute, relative paths, uri's), objBitmap is always null.
ADB says that "photo.jpg" has -rwxrwx--- rights, and though I'm not entirely sure, I think that should be more than sufficient
On the other hand, maybe the intent still has a lock on "photo.jpg"? Or something else is going on...
And one final note, I'm using System.IO.File.ReadAllText just for testing purposes. I experimented with stream readers as well, but with the same result. Also, though I believe this step is unnecessary, I enabled "WriteExternalStore" in the Manifest
namespace CameraAppDemo
{
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics;
using Android.OS;
using Android.Provider;
using Android.Widget;
using Java.IO;
using Environment = Android.OS.Environment;
using Uri = Android.Net.Uri;
[Activity(Label = "Camera App Demo", MainLauncher = true)]
public class MainActivity : Activity
{
private File _file;
private string _basePath;
private ImageView _imageView;
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
var objBitmap = BitmapFactory.DecodeFile(_file.AbsolutePath) ;
Console.WriteLine ("objBitmap = null : " + (objBitmap == null).ToString ());
var strOutput = System.IO.File.ReadAllText (FileManager.BasePath + "/photo.jpg");
Console.WriteLine (strOutput);
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
FileManager.SetupFolderStructure();
if (IsThereAnAppToTakePictures())
{
Button button = FindViewById<Button>(Resource.Id.myButton);
_imageView = FindViewById<ImageView>(Resource.Id.imageView1);
button.Click += TakeAPicture;
}
}
private bool IsThereAnAppToTakePictures()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
IList<ResolveInfo> availableActivities = PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
return availableActivities != null && availableActivities.Count > 0;
}
private void TakeAPicture(object sender, EventArgs eventArgs)
{
System.IO.Directory.Delete (FileManager.BasePath, true);
_basePath = FileManager.BasePath;
_file = new Java.IO.File (_basePath, "photo.jpg");
Intent intent = new Intent(MediaStore.ActionImageCapture);
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(_file));
StartActivityForResult(intent, 0);
}
}
}
//Part of the FileManager class:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Android.Graphics;
namespace CameraAppDemo
{
public class FileManager
{
public static string BasePath {
get {
var libraryPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
if (Directory.Exists (libraryPath) == false) {
Directory.CreateDirectory (libraryPath);
}
return libraryPath;
}
}
}
}
==== Edit ====
It seems that I'm simply not able to read the file. As an ex-webdeveloper, I'm fairly new to programming for mobile, let alone the combo of C# and Java and I'm still learning a lot.
Anyway, I added the following lines:
Console.WriteLine("Setting file :" + _file.SetReadable (true));
Console.WriteLine("Can read :" + _file.CanRead());
Both cases return False. I can't read the file, and I am unable to give read access.
So, any ideas? Is this by design? Can I tell the Intent for taking images to give me read access, or is there another workaround?
If everything fails, I'm hoping to workaround the problem by saving to the SD card first and then copying the file to the local filesystem. But that's something I rather would not do; I can't guarantee that the end users have an SD card, and the pictures should not be deleted by accident.

How to get Monotorrents DHT to work?

Iam trying to get the dht implementation of monotorrent to work but i just cant seem to find any peers.
ive tried most of the examplecode code availeble on the net like the testclient and dhttest.
I have tried with several diffrent infohashes.
Anyone here got it working? or do you know where i can find the devs?
This is how my code looks atm:
using System;
using System.Collections.Generic;
using System.Text;
using MonoTorrent.Dht;
using MonoTorrent.Dht.Listeners;
using System.Net;
using System.IO;
using MonoTorrent.Common;
using MonoTorrent.Tracker.Listeners;
namespace SampleClient
{
class Program
{
static void Main(string[] args)
{
string basePath = Environment.CurrentDirectory;
string torrentsPath = Path.Combine(basePath, "Torrents");
Torrent torrent = null;
// If the torrentsPath does not exist, we want to create it
if (!Directory.Exists(torrentsPath))
Directory.CreateDirectory(torrentsPath);
// For each file in the torrents path that is a .torrent file, load it into the engine.
foreach (string file in Directory.GetFiles(torrentsPath))
{
if (file.EndsWith(".torrent"))
{
try
{
// Load the .torrent from the file into a Torrent instance
// You can use this to do preprocessing should you need to
torrent = Torrent.Load(file);
Console.WriteLine(torrent.InfoHash.ToString());
}
catch (Exception e)
{
Console.Write("Couldn't decode {0}: ", file);
Console.WriteLine(e.Message);
continue;
}
}
}
DhtListener listener = new DhtListener(new IPEndPoint(IPAddress.Parse("192.168.2.3"), 10000));
DhtEngine engine = new DhtEngine(listener);
//engine.RegisterDht(dht);
byte[] nodes = null;
if (File.Exists("mynodes"))
nodes = File.ReadAllBytes("mynodes");
listener.Start();
int i = 0;
bool running = true;
StringBuilder sb = new StringBuilder(1024);
while (running)
{
engine.Start(nodes);
while (Console.ReadLine() != "q")
{
engine.GetPeers(torrent.InfoHash);
}
File.WriteAllBytes("mynodes", engine.SaveNodes());
}
}
}
}
I know it's very old question, I'm not sure why it's still noone has answer it, anyway. The problem seem to be this line:
DhtListener listener = new DhtListener(new IPEndPoint(IPAddress.Parse("192.168.2.3"), 10000));
This ip is not the real ip, so you actually asl peers to send the respone to unkonw adress.
What to do? register your own adress.

Categories

Resources