PlaylistLoader() not found in NAudio c# - c#

private void LoadPlaylist(object p)
{
var ofd = new OpenFileDialog();
ofd.Filter = "PLAYLIST files (*.playlist) | *.playlist";
string abc = ofd.ShowDialog().ToString();
if (abc == "OK")
{
Playlist = new PlaylistLoader().Load(ofd.FileName).ToObservableCollection(); // load the playlist
}
}
I try to implement an Audio Player using NAudio. I use the reference https://www.pluralsight.com/guides/microsoft-net/building-a-wpf-media-player-using-naudio
But "PlaylistLoader" class was not found. "Playlist" is an ObservableCollection of type "Track". I try to add audio file to Track object as hadcoded, but failed. Anyone familiar with NAudio please help.

PlaylistLoader is not part of NAudio. It is a helper class created by the author of that article, so you should download the source if available or ask the author to provide code

Related

How to create a button which takes a picture

I'm writing a cross-platform (iOS and Android) app in C# using Xamarin on Visual Studio Community 2022. I have implemented a camera preview on the app using the code found at this website :
https://www.c-sharpcorner.com/article/creating-a-custom-camera-view-basic-concept-create-half-screen-camera-in-xamari/
The code on the website is for iOS, but there is a link at the bottom to download a folder which contains the code for Android as well. My app now displays a camera preview, but there is no way to take a picture with this. I therefore want to create a button which takes a picture without having to open the camera app. I'd also like the resulting photo to not be saved in the photos of the phone. I have looked but have found no way of doing exactly what I want, and therefore I don't know where to get started. If the answer could give as many details as possible about how to do this for both platforms it would be appreciated. Also, would the resulting photo be of the type FileResult? I have previously worked with the mediapicker in Xamarin which returns the type FileResult, but have come to realize that there are limitations within the mediapicker and I therefore can't work with it.
Thanks a lot :)
You can try MediaPicker to capture picture.And get the filepath in photo.FullPath.
You can refer to the link below to get more details:
https://learn.microsoft.com/en-us/xamarin/essentials/media-picker?tabs=ios
edit:
private void cameraView_MediaCaptured(object sender, Xamarin.CommunityToolkit.UI.Views.MediaCapturedEventArgs e)
{
byte[] image = e.ImageData;
DependencyService.Get<ISaveService>().wirteFile("pic.jpg", image);
}
public interface ISaveService
{
void SaveFile(string fileName, byte[] data);
}
Android:
[assembly: Xamarin.Forms.Dependency(typeof(SaveService))]
namespace cameraviewDemo.Droid
{
public class SaveService: ISaveService
{
void ISaveService.SaveFile(string fileName, byte[] data)
{
string picPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryPictures);
string filePath = Path.Combine(picPath, fileName);
File.WriteAllBytes(filePath, data);
}
}
}
iOS:
[assembly: Xamarin.Forms.Dependency(typeof(SaveService))]
namespace cameraviewDemo.iOS
{
class SaveService: ISaveService
{
void ISaveService.SaveFile(string fileName, byte[] data)
{
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filename = Path.Combine(documents, fileName);
File.WriteAllBytes(filename, data);
}
}
}

C# custom file extension filter

I'm trying to read a list of documents in a directory. I understand how the filter modifiers work at a high level and have used them before. However, this time I need to filter something that doesn't have a standardized extension (i.e. "*.txt" or *.pdf").
I'm using the example as found on....
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.filedialog.filter?view=net-5.0
using System;
using System.Windows.Forms;
namespace COMS2412_Readin
{
public partial class Form1 : Form
{
string Serial_num = null;
string INI_file_dir_temp = null;
string CONFIG_data = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Allow user to enter serial number and load it for useage later.
Serial_num = Serial_number_text.Text;
try
{
using (OpenFileDialog COMS_file_dialog = new OpenFileDialog())
{
COMS_file_dialog.InitialDirectory = "c:\\";
//Have dialog box filter out all files without the .INI extention.
COMS_file_dialog.Filter = "txt files (*.INI)|*.INI|All files (*.*)|*.*"; //Failed
// COMS_file_dialog.Filter = "*.INI"; //Failed
// COMS_file_dialog.Filter = "(*.INI)"; //Failed
// COMS_file_dialog.Filter = "(INI files | *.INI)"; //Failed
COMS_file_dialog.FilterIndex = 2;
COMS_file_dialog.RestoreDirectory = true;
if (COMS_file_dialog.ShowDialog() == DialogResult.OK)
{
//Check to make sure it was the correct file type.
INI_file_dir_temp = COMS_file_dialog.FileName;
}
}
}
catch
{
//Sorry there was an error with opening the file. Please ensure the file is not currently open.
}
}
}
}
The project I'm working on imports config files from an external piece of equipment. The problem is there are literally thousands of files, each with unusual file extensions. For example *.INI is one of the extensions I want to filter. I've tried just entering `*.INI as the argument but it didn't work. What am I missing? Is there a way to alter...
openFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
to filter specific file extensions?
Finally, have something that works...
openFileDialog.Filter = "(*.INI)|*.INI";
This filters out everything that isn't of the .INI extension. For me specifically, I had to run VS as admin and ensure the files were not hidden.

Trouble with transfer function in WIA C#

I have a problem with the below code. I want to scan a document by clicking a button in a WinForms C# application.
I use WIA, Visual studio and the scanner Fujitsu N7100A working with Windows 8. I am following a tutorial online for using WIA.
But the program doesn't run as expected. It seems to break down at the Transfer method.
// Create a DeviceManager instance
var deviceManager = new DeviceManager();
// Create an empty variable to store the scanner instance
DeviceInfo firstScannerAvailable = null;
// Loop through the list of devices to choose the first available
AddLogs(deviceManager.DeviceInfos.Count.ToString(), filename);
foreach (DeviceInfo d in deviceManager.DeviceInfos)
{
if (d.Type == WiaDeviceType.ScannerDeviceType)
{
firstScannerAvailable = d;
}
}
// Connect to the first available scanner
var device = firstScannerAvailable.Connect();
// Select the scanner
var scannerItem = device.Items[0];
// Retrieve a image in JPEG format and store it into a variable
var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatPNG);
//Save the image in some path with filename
var path = #"C:\Documents\scan.png";
if (File.Exists(path))
{
File.Delete(path);
}
// Save image !
imageFile.SaveFile(path);
I just have to remove the addition of lines in the file of log.
This is much more of a workaround since i have no idea about your scanner.
I would assume that all scanners has a drive where they store their scanned documents, like mine, So i would suggest that you read all available drives loop through them check for DriveType and VolumeLabel and then read it's files and copy the document where you want
Something like this :
foreach (var item in DriveInfo.GetDrives())
{
//VolumeLabel differs from a scanner to another
if (item.VolumeLabel == "Photo scan" && item.DriveType == DriveType.Removable)
{
foreach (var obj in Directory.GetFiles(item.Name))
{
File.Copy(obj, "[YOUR NEW PATH]");
break;
}
break;
}
}
Finaly a TWAIN application work with this scanner. I will work with that. I don't said why do that work with TWAIN and not with WIA but that the reality. Sorry for this waste of time. Thank you for the answers. Have a nice day.
I am currently solving this very problem. It seems the N7100A driver sets the Pages property of the device to 0, which should mean continous scanning, but the transfer method is unable to handle this value. You must set that property to 1:
var pages = 1;
// Not all devices have this property, but Fujitsu N7100A has.
device.Properties["Pages"]?.set_Value(ref pages);
I think the problem is here
var scannerItem = device.Items[0];
as WIA indexes are NOT zero based so it should be 1 instead
var scannerItem = device.Items[1];

Closed Captions resolving error System.UnauthorizedAccessException

So, I'm trying to implement closed captions support to my UWP video player (using MediaElement), I've followed this example to do so.
I'm getting an error when resolving it called "Error resolving track due to error NetworkError System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
I do it like this: I open a file using filepicker and then get the SRT of the video that was picked. After that I show it. Unfortunately, nothing appears.
Here is my OpenButton function:
private async void BtnOpenMedia_Click(object sender, RoutedEventArgs e)
{
FileOpenPicker filePicker = new FileOpenPicker();
filePicker.ViewMode = PickerViewMode.Thumbnail;
filePicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
filePicker.FileTypeFilter.Add(".mp4");
filePicker.FileTypeFilter.Add(".wmv");
filePicker.FileTypeFilter.Add(".mpg");
filePicker.FileTypeFilter.Add(".mpeg");
filePicker.FileTypeFilter.Add("*");
StorageFile storageFile = await filePicker.PickSingleFileAsync();
if (storageFile != null && mElement != null)
{
string strSource = Path.GetDirectoryName(storageFile.Path) + #"\" + storageFile.DisplayName + ".srt";
var mediaSource = MediaSource.CreateFromStorageFile(storageFile);
var ttsStream = TimedTextSource.CreateFromUri(new Uri(strSource));
ttsStream.Resolved += TtsStream_Resolved;
mediaSource.ExternalTimedTextSources.Add(ttsStream);
var mediaPlayback = new MediaPlaybackItem(mediaSource);
mElement.SetPlaybackSource(mediaPlayback);
}
}
Here is my resolve function:
private void TtsStream_Resolved(TimedTextSource sender, TimedTextSourceResolveResultEventArgs args)
{
if (args.Error != null)
{
var ignoreAwaitWarning = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
var msg = new MessageDialog("Error resolving track " + " due to error " + args.Error.ErrorCode + " " + args.Error.ExtendedError);
await msg.ShowAsync();
});
return;
}
}
P.S: Also, I don't know if this is duplicated or not, that's why I'm adding it in this but I've done my research and found nothing. How to preview frames of MediaElement ? For example like YouTube you can preview thumbnails in the slider, I don't know how to achieve that, thanks!
You used a FileOpenPicker to select the Video file, but use a Path to access the .srt file. The .srt file is also in the Video file's folder. I reproduced your problem here:
The error message is clear, you have no access to this file, this file indicates the .srt file, so the problem is where did you store this .srt file. Just have a test, seems TimedTextSource.CreateFromUri(Uri) | createFromUri(Uri) method does not support to access the files in the local machine, but you can use TimedTextSource.CreateFromStream(IRandomAccessStream) | createFromStream(IRandomAccessStream) method for example like this:
if (storageFile != null && mElement != null)
{
//string strSource = Path.GetDirectoryName(storageFile.Path) + #"\" + storageFile.DisplayName + ".srt";
var fileSource = await KnownFolders.VideosLibrary.GetFileAsync(storageFile.DisplayName + ".srt");
IRandomAccessStream strSource = await fileSource.OpenReadAsync();
var mediaSource = MediaSource.CreateFromStorageFile(storageFile);
//var ttsStream = TimedTextSource.CreateFromUri(new Uri(strSource));
var ttsStream = TimedTextSource.CreateFromStream(strSource);
ttsStream.Resolved += TtsStream_Resolved;
mediaSource.ExternalTimedTextSources.Add(ttsStream);
var mediaPlayback = new MediaPlaybackItem(mediaSource);
mediaPlayback.TimedMetadataTracksChanged += (sender1, args) =>
{
mediaPlayback.TimedMetadataTracks.SetPresentationMode(0, TimedMetadataTrackPresentationMode.PlatformPresented);
};
mElement.SetPlaybackSource(mediaPlayback);
}
When using this code, the .srt file and video file should in the Video lib and the capability "Videos Library" should be enabled in the manifest.
In an UWP app, you can only access the files in known folder like picture lib, music lib and video lib and doc lib or local folder of your app, if your video is not in these folders, you should also handle the exception when access is denied in this scenario.
How to preview frames of MediaElement ? For example like YouTube you can preview thumbnails in the slider.
For this question, I can't find any ready-made sample for you, but I think the scenario 4 of official Media editing sample can be a direction, it shows a overlay layer on MediaElement, maybe you can set the "baseVideoFile" and the "overlayVideoFile" with the same source. The problem is when and where to show this overlay layer, it's related to the transport control of MediaElement. This is for now just a mind, you can have a try.

Playing NAudio .mp3 through an Audio Source in Unity

I'm using a package called Visualizer Studio (http://www.alteredr.com/visualizer-studio/) to make a game where objects react to music. My goal is to have the user be able to load a song at any time during the game. It's going to be standalone/PC, not WebPlayer.
My problem is that Visualizer Studio takes the audio data from an Audio Source in the scene. So when I use NAudio to load and stream MP3s, visualizer studio doesn't hear them, and my objects don't react to the music.
I'm using IWavePlayer right now in my code. I've tried adding audio.clip = www.GetAudioClip and similar functions to have the audio clip load the music that is being played, but to no avail.
I got the code I'm using to select and stream .mp3s from this blog post (the source code is at the bottom): (http://denis-potapenko.blogspot.com/2013/04/task-6-loading-mp3-audio-via-www-class.html). It's unchanged at the moment, because nothing I was trying was working.
To be clear, the .mp3s DO play when I select them from a file browser. I just need them to play via an audio source in my scene. Please, there has to be a way to do this. I've contacted visualizer studio support and asked on the unity forums, but nobody can help so far.
Please keep in mind that I'm not exactly a great programmer, so you might have to dumb answers down for me. Thanks for you patience in advance. Anyway,
Here's my code I'm using to open a file browser and stream audio:
using UnityEngine;
using System.Collections;
using System.IO;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using NAudio;
using NAudio.Wave;
public class AppRoot : MonoBehaviour
{
///////////////////////////////////////////////////////////////////////////
#region Variables
private static AppRoot mInstance = null;
private const string cLocalPath = "file://localhost/";
private IWavePlayer mWaveOutDevice;
private WaveStream mMainOutputStream;
private WaveChannel32 mVolumeStream;
#endregion
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
#region Interface
public AppRoot()
{
mInstance = this;
}
public void Start()
{
}
public void Update()
{
if(Input.GetKeyDown(KeyCode.F))
{
UnloadAudio();
LoadAudio();
}
}
public void OnGUI()
{
if (GUI.Button(new Rect(100, Screen.height - 200 + 100, Screen.width - 200, 35), "Load audio"))
{
UnloadAudio();
LoadAudio();
}
}
public void OnApplicationQuit()
{
UnloadAudio();
}
#endregion
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
#region Implementation
private void LoadAudio()
{
System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
ofd.Title = "Open audio file";
ofd.Filter = "MP3 audio (*.mp3) | *.mp3";
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
WWW www = new WWW(cLocalPath + ofd.FileName);
Debug.Log("path = " + cLocalPath + ofd.FileName);
while (!www.isDone) { };
if (!string.IsNullOrEmpty(www.error))
{
System.Windows.Forms.MessageBox.Show("Error! Cannot open file: " + ofd.FileName + "; " + www.error);
return;
}
byte[] imageData = www.bytes;
if (!LoadAudioFromData(imageData))
{
System.Windows.Forms.MessageBox.Show("Cannot open mp3 file!");
return;
}
mWaveOutDevice.Play();
Resources.UnloadUnusedAssets();
}
}
private bool LoadAudioFromData(byte[] data)
{
try
{
MemoryStream tmpStr = new MemoryStream(data);
mMainOutputStream = new Mp3FileReader(tmpStr);
mVolumeStream = new WaveChannel32(mMainOutputStream);
mWaveOutDevice = new WaveOut();
mWaveOutDevice.Init(mVolumeStream);
return true;
}
catch (System.Exception ex)
{
Debug.LogWarning("Error! " + ex.Message);
}
return false;
}
private void UnloadAudio()
{
if (mWaveOutDevice != null)
{
mWaveOutDevice.Stop();
}
if (mMainOutputStream != null)
{
// this one really closes the file and ACM conversion
mVolumeStream.Close();
mVolumeStream = null;
// this one does the metering stream
mMainOutputStream.Close();
mMainOutputStream = null;
}
if (mWaveOutDevice != null)
{
mWaveOutDevice.Dispose();
mWaveOutDevice = null;
}
}
#endregion
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
#region Properties
private static AppRoot Instance
{
get
{
return mInstance;
}
}
#endregion
///////////////////////////////////////////////////////////////////////////
}
Sincerely,
Jonathan
http://answers.unity3d.com/answers/1128204/view.html
With the "latest" version of NAudio.dll and NAudio.WindowsMediaFormat.dll inserted into your Resources folder utilize this code to do what you described:
var musicInput : GameObject;
private var aud : AudioFileReader;
private var craftClip : AudioClip;
private var AudioData : float[];
private var readBuffer : float[];
private var soundSystem : AudioSource;
private var musicPath : String[];
//Check if there's a pref set for the music path. Use it AND add all the files from it
function CheckMusic()
{
var pathname = musicInput.GetComponent.<InputField>();
if(PlayerPrefs.HasKey("musicpath") == false)
{
PlayerPrefs.SetString("musicpath", "Enter Music Directory");
}
else
{
pathname.text = PlayerPrefs.GetString("musicpath");
musicPath = Directory.GetFiles(PlayerPrefs.GetString("musicpath"),"*.mp3");
}
}
function LoadSong(songToPlay : int)
{
//Download the song via WWW
var currentSong : WWW = new WWW(musicPath[songToPlay]);
//Wait for the song to download
if(currentSong.error == null)
{
//Set the title of the song
playingSong.text = Path.GetFileNameWithoutExtension(musicPath[songToPlay]);
//Parse the file with NAudio
aud = new AudioFileReader(musicPath[songToPlay]);
//Create an empty float to fill with song data
AudioData = new float[aud.Length];
//Read the file and fill the float
aud.Read(AudioData, 0, aud.Length);
//Create a clip file the size needed to collect the sound data
craftClip = AudioClip.Create(Path.GetFileNameWithoutExtension(musicPath[songToPlay]),aud.Length,aud.WaveFormat.Channels,aud.WaveFormat.SampleRate, false);
//Fill the file with the sound data
craftClip.SetData(AudioData,0);
//Set the file as the current active sound clip
soundSystem.clip = craftClip;
}
}
And I quote
The "songToPlay" variable that is passed to the function is a simple int that is acquired from the array created under the CheckMusic function. I search a chosen directory entered from a GUI Inputfield for a specific file type (MP3) which can be changed to WAV or OGG and then input those files to an array. Other code chooses the number of the song on the array to play and you can change that to anything you like. The important part is that the NAudio,dll does all the heavy lifting. All you need to do is use the aud.Read(float[] to send data to, song starting point(usually 0),length of song data (aud.length). The Float[] here is the same length as aud.length so create the float of the same length, read the file, fill the float, create the clip, then dump the float data in with AudioClip.SetData()
Right now this code works and it does the job. Downside is it takes
2-3 seconds to fill the float in this way and is a noticeable drag. It
also tends to chew up memory pretty fast, but it gets the job done.
Hope it helps as a starting point for those who are looking to do
this. I know I needed it.
When you use a WaveOut instance you are playing (relatively) directly on the soundcard, outside of the Unity environment. You need a way to introduce that data into Unity.
I haven't worked with Unity so this might not be the best answer,but...
You can introduce wave data into the scene using OnAudioFilterRead. You can use this to create procedural sound, and with a little coding it can presumably be hooked up to a NAudio wave source. This will introduce the audio data directly into the game for your in-game code to deal with.
Here's an article I found that might help: Procedural Audio with Unity
mWaveOutDevice = new WaveOut();
Maybe causing the issue, it is better practice to use WaveOutEvent() which supports running in all non GUI threads.
mWaveOutDevice = new WaveOutEvent();
Related StackOverFlow Question

Categories