Play audio at two different Audiodevices simultaneously with Naudio - c#

My question is similar to one here :
Play audio to two different Audiodevices simultaneously with Naudio
But i ask it here again since it has not been answered clearly in the link above.
I also have it at:
Play sound in both speaker and headset wpf
Inspiration from :
Play a sound in a specific device with C#
I am adding source code and adding the NAudio tag here as well.
I have an wpf application and i am using the soundPlayer class to play sound (for eg ringtone). Currently the tone plays either on speakers or on the headset (if its plugged in). I would like the application to play the tone on speaker even when the headsets are plugged in. I know there are ways to do this in android, but couldn't find any in wpf. I would also like an UI for the user to choose the devices in which he would like to hear sound. Any help is appreciated. Thanks !
public void detectDevices()
{
int waveOutDevices = WaveOut.DeviceCount;
switch (waveOutDevices)
{
case 1:
var wave1 = new WaveOut();
wave1.DeviceNumber = 0;
playSound(0);
break;
case 2:
var wave2 = new WaveOut();
wave2.DeviceNumber = 0;
playSound(0);
var wave3 = new WaveOut();
wave3.DeviceNumber = 1;
playSound(1);
break;
}
}
public void playSound(int deviceNumber)
{
disposeWave();// stop previous sounds before starting
waveReader = new NAudio.Wave.WaveFileReader(fileName);
var waveOut = new NAudio.Wave.WaveOut();
waveOut.DeviceNumber = deviceNumber;
output = waveOut;
output.Init(waveReader);
output.Play();
}
public void disposeWave()
{
if (output != null)
{
if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing)
{
output.Stop();
output.Dispose();
output = null;
}
}
if (wave != null)
{
wave.Dispose();
wave = null;
}
}
case eSelector.startIncomingRinging:
fileName = ("Ring.wav");
detectDevices();
I still hear ringtone just in one device (either in headset or speakers) using the code above.

You need two instances of WaveOut, one for each soundcard. And then the simplest way if you are playing from file, is to also have two instances of WaveFileReader. You can't easily synchronize them I'm afraid, you'll just have to start them both playing together and hope for the best.
The wave1, wave2 and wave3 classes in your code above do abosolutely nothing. The audio will be played with the WaveOut device you create in playSound. You seem to have a single class property called output and another called waveReader, when you need two of each.

Related

USB Printing for DOT Matrix POS printer

I was trying to print to an usb printer using usbmanager, the App can detect the printer device but when i run it doesnt print. there are no errors and all passing data is ok.
Printer : Bixolon SRP 275III
Type: USB
private async void printReciept()
{
UsbManager m_usbManager;
m_usbManager = (UsbManager)Application.Context.GetSystemService(Context.UsbService);
var deviceList = m_usbManager.DeviceList;
IEnumerable<UsbDevice> deviceIterator = deviceList.Values.AsEnumerable();
UsbDevice m_usbdevice = null;
if (deviceIterator.Count() > 0)
{
var device = deviceIterator.ElementAt(0);
m_usbdevice = device;
string ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
var mPermissionIntent = PendingIntent.GetBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
m_usbManager.RequestPermission(m_usbdevice, mPermissionIntent);
UsbDeviceConnection deviceConnection = null;
try
{
using (var usbInterface = m_usbdevice.GetInterface(0))
{
using (var usbEndpoint = usbInterface.GetEndpoint(0))
{
mEndPoint = usbEndpoint;
deviceConnection = m_usbManager.OpenDevice(m_usbdevice);
byte[] bytesHello = Encoding.UTF8.GetBytes("Hello");
deviceConnection.BulkTransfer(usbEndpoint, bytesHello, bytesHello.Length, 0);
}
}
}
catch
{
}
}
}
You are sending the string to be printed directly to the bulk endpoint, or actually you are doing bulk transfer to the first endpoint found without knowing any of it's characteristics? I think it is a bit more complex than that.
First try to find out whether your printer supports USB printing class or some proprietary implementation. You can do this easily e.g. by connecting the printer to Windows PC and looking from the device manager, usbdeview or some other similar application.
If it supports printing class, read this document and implement your driver based on that (or use the one you may already have in Android). If it only supports proprietary implementation, you need to get the specifications for it or do some reverse engineering.
You may need to learn about PCL which may also be needed.

Speech recognition only listens for Commands in my dictionary?

Okay so i am working on my program. The problem is that whenever spymode = true, it doesnt register whatever i am saying to the text file. It just registers the set commands in "CommandsList" dictionary. So whenever i say like "twitch" which is a command in that dictionary it will write that to the spymodeLog.txt file. But whenever i say something that is not a command, for example "hello my name is Robin" , that will not be written to the .txt file. It only takes commands in my dictionary and outputs it to the file whenever i say them. Why is this? and how can i fix it? really odd.
static Dictionary<string, string> CommandsList = new Dictionary<string, string>();
internal static void recEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (keyHold == true)
{
string command = "";
if (CommandsList.TryGetValue(e.Result.Text, out command))
{
System.Diagnostics.Process.Start(command);
}
}
if (spymode == true)
{
DateTime now = DateTime.Now;
string path = Application.StartupPath + "spymodeLog.txt";
if (File.Exists(path))
{
using (StreamWriter wr = File.AppendText(path))
{
wr.WriteLine(e.Result.Text.ToString());
}
}
else if(!File.Exists(path))
{
using (var wr = new StreamWriter("spymodeLog.txt", true))
{
wr.WriteLine(e.Result.Text.ToString());
}
}
}
}
SpeechRecognized event fire when a command from the dictionnary has been recognized, hence the name of the event.
What you want is the SpeechDetected event which from the help says it fire when it recognize something has been said.
Each speech recognizer has an algorithm to distinguish between silence and speech. When the SpeechRecognitionEngine performs a speech recognition operation, it raises the SpeechDetected event when its algorithm identifies the input as speech.
This event will allow you to get the actual position when an audio was captured. This allow you to go find that audio portion and save it to a file or send it in the methods that allow you to convert audio to text (i do not remember the methods but they are there, i have used it in the past)
Second method which doesn't work on everyone computer. 1 out of 3 of my PC actually works with this method and this method is to create an instance of a special grammar disctionnary called DictationGrammar
What you do is create a new instance of this class. You have 3 ways to do so, either normal, spelling or default of the computer accessbility option.
default computer accessibility :
var grammar = new DictationGrammar();
Normal :
var grammar = new DictationGrammar("grammar:dictation");
Spelling :
var grammar = new DictationGrammar("grammar:dictation#spelling");
than use that dictionnary with the combinaison of all those you want and you can create a tree of choices that lead to the generic recognition. Me in my old app i used to have the keyword "Note" that had to be said and then it was falling on the DictationGrammar and started to recognize all text.
Since it didn't work on all computers while other commands where perfectly working i assumed it has something to do with wrong language of dictation grammar being loaded or something like that but there was no option to change that so i went with SpeechDetected and converted the audio to text myself.

Video is still downloaded after releasing an AVPlayer instance

I have problems with my video player that uses the AV Foundation API and plays a clip via HTTP progressive download. Even when the AVPlayer is released, I'm still downloading the video clip (observed via an HTTP Traffic sniffer).
My player is initialized like that:
m_player = new AVPlayer();
m_playerLayer = new AVPlayerLayer();
m_playerLayer.Player = m_player;
Then, when I have the URL of the video:
m_url = new NSUrl (...);
m_asset = new AVAsset(m_url);
m_asset.AddObserver(this, new NSString ("playable"), NSKeyValueObservingOptions.Initial | NSKeyValueObservingOptions.New, AVPlayerAssetObservationContext);
When I'am notified that the asset is playable, I'm creating an AVPlayerItem:
m_playerItem = new AVPlayerItem(m_asset);
if (m_player.CurrentItem != m_playerItem)
{
m_player.ReplaceCurrentItemWithPlayerItem (m_playerItem);
}
My video is playing without any problems. Then, when I press a back button, I have a mechanism that call a Destroy() method. Here I tried a lot of things to be sure that my player is well released:
if(m_player != null)
{
m_player.Pause();
m_player.Dispose();
m_player = null;
}
if(m_playerLayer != null)
{
m_playerLayer.Dispose();
m_playerLayer = null;
}
if(m_playerItem != null)
{
m_playerItem.Dispose();
m_playerItem = null;
}
if(m_asset != null)
{
m_asset.CancelLoading();
m_asset.RemoveObserver(this, new NSString("playable"));
m_asset.Dispose();
m_asset = null;
}
if(m_url != null)
{
m_url.Dispose();
m_url = null;
}
I tested my app with a debugger and for sure, I'am falling into this code. My objects seems to be well released, but for sure the application is still downloading the video url. Am I doing something wrong in the init / release code?
Thank in advance for your help!
The workaround I found is to add this line in the Destroy() code
m_player.ReplaceCurrentItemWithPlayerItem(new AVPlayerItem());
The video download is then interrupted.

Taking input from a joystick with C# .NET

I searched around on Google for this, but the only things I came up with were outdated and did not work.
Does anyone have any information on how to get joystick data using C# .NET?
Since this was the top hit I got on google while researching joystick / gamepad input in C#, I thought I should post a response for others to see.
The easiest way I found was to use SharpDX and DirectInput. You can install it via NuGet (SharpDX.DirectInput)
After that, it's simply a matter of calling a few methods:
Sample code from SharpDX
static void Main()
{
// Initialize DirectInput
var directInput = new DirectInput();
// Find a Joystick Guid
var joystickGuid = Guid.Empty;
foreach (var deviceInstance in directInput.GetDevices(DeviceType.Gamepad,
DeviceEnumerationFlags.AllDevices))
joystickGuid = deviceInstance.InstanceGuid;
// If Gamepad not found, look for a Joystick
if (joystickGuid == Guid.Empty)
foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick,
DeviceEnumerationFlags.AllDevices))
joystickGuid = deviceInstance.InstanceGuid;
// If Joystick not found, throws an error
if (joystickGuid == Guid.Empty)
{
Console.WriteLine("No joystick/Gamepad found.");
Console.ReadKey();
Environment.Exit(1);
}
// Instantiate the joystick
var joystick = new Joystick(directInput, joystickGuid);
Console.WriteLine("Found Joystick/Gamepad with GUID: {0}", joystickGuid);
// Query all suported ForceFeedback effects
var allEffects = joystick.GetEffects();
foreach (var effectInfo in allEffects)
Console.WriteLine("Effect available {0}", effectInfo.Name);
// Set BufferSize in order to use buffered data.
joystick.Properties.BufferSize = 128;
// Acquire the joystick
joystick.Acquire();
// Poll events from joystick
while (true)
{
joystick.Poll();
var datas = joystick.GetBufferedData();
foreach (var state in datas)
Console.WriteLine(state);
}
}
I hope this helps.
I even got this to work with a DualShock3 and the MotioninJoy drivers.
One: use SlimDX.
Two: it looks something like this (where GamepadDevice is my own wrapper, and the code is slimmed down to just the relevant parts).
Find the joystick / pad GUIDs:
public virtual IList<GamepadDevice> Available()
{
IList<GamepadDevice> result = new List<GamepadDevice>();
DirectInput dinput = new DirectInput();
foreach (DeviceInstance di in dinput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly))
{
GamepadDevice dev = new GamepadDevice();
dev.Guid = di.InstanceGuid;
dev.Name = di.InstanceName;
result.Add(dev);
}
return result;
}
Once the user has selected from the list, acquire the gamepad:
private void acquire(System.Windows.Forms.Form parent)
{
DirectInput dinput = new DirectInput();
pad = new Joystick(dinput, this.Device.Guid);
foreach (DeviceObjectInstance doi in pad.GetObjects(ObjectDeviceType.Axis))
{
pad.GetObjectPropertiesById((int)doi.ObjectType).SetRange(-5000, 5000);
}
pad.Properties.AxisMode = DeviceAxisMode.Absolute;
pad.SetCooperativeLevel(parent, (CooperativeLevel.Nonexclusive | CooperativeLevel.Background));
pad.Acquire();
}
Polling the pad looks like this:
JoystickState state = new JoystickState();
if (pad.Poll().IsFailure)
{
result.Disconnect = true;
return result;
}
if (pad.GetCurrentState(ref state).IsFailure)
{
result.Disconnect = true;
return result;
}
result.X = state.X / 5000.0f;
result.Y = state.Y / 5000.0f;
int ispressed = 0;
bool[] buttons = state.GetButtons();
The bad news is that Microsoft seems to stop supporting their NET libraries for DirectX and focus on XNA instead. I don't work in GameDev so I don't need to use XNA but you may try it if you developing computer games. The good news is that there are other approaches. One is SlimDX the new framework to help you to wok with DirectX from C#. The other way is to directly add references of "Microsoft.DirectX.dll" and "Microsoft.DirectX.DirectInput.dll" to your project. you can find them "..\Windows\Microsoft.NET\DirectX for Managed Code\". if you you are going to use last approach here is a link to codeproject where you can read how to work with a joystick.
EDIT:
If your application is based on NET version newer then 2.0 the application may hang on. To fix this problem change config file and add this:
<startup useLegacyV2RuntimeActivationPolicy="true">
Google led me here and while not a requirement of this question, OpenTK is a good option for Windows and Linux (under mono) support.
From the OpenTK docs, this code works on Raspberry Pi + Raspbian + Mono 3.12.0:
for (int i = 0; i < 4; i++)
{
var state = Joystick.GetState(i);
if (state.IsConnected)
{
float x = state.GetAxis(JoystickAxis.Axis0);
float y = state.GetAxis(JoystickAxis.Axis1);
// Print the current state of the joystick
Console.WriteLine(state);
}
}
This question is old, but it seems to be active even to this day, so I'm posting anyway.
If you need to get input from XInput only, take a look at XInputium. This is a .NET library that is specialized in XInput controllers. It is pretty straightforward, and has many code samples you can look at.

Read Song Title/Artist from a live audio stream with Silverlight 4?

I have a SL4 project that is successfully streaming a great sounding WMA audio stream from a remote location. All of the MediaElement actions are straight forward.
What I want to do is read the attributes that are passed as text along with the Audio stream. For instance the encoder of the stream embeds the title of the stream, the title of the song playing and the name of the artist for the current song.
How would I pick this out using Silverlight 4 and then display it in a Label to the user?
It sure would be easier than writing a bunch of web services to do the same thing. Windows Media Player and WinAmp all get the information I am just not seeing it in the MediaElement object collection.
I found the answer after searchting the web as well as fiddling with Expression 3 a little as well.
It turns out that a live audio stream has markers that are sent across as well as the audio. Markers can contain almost anything but one is called a "Caption". The caption is basically a free-form string field that you can read. With my stream the encoder sends a lot of information across as a caption that can then be broken down. So here is the code I am using:
Starts with registering a few events, the last one is the important one.
public MainPage()
{
InitializeComponent();
this.mediaElement1.BufferingProgressChanged += new RoutedEventHandler(mediaElement1_BufferingProgressChanged);
this.mediaElement1.MarkerReached += new TimelineMarkerRoutedEventHandler(mediaElement1_MarkerReached);
}
Then the actual marker handler does the following:
private void mediaElement1_MarkerReached(object sender, TimelineMarkerRoutedEventArgs e)
{
Dictionary<string, string> songAttribs = new Dictionary<string, string>();
string playerFeed = HttpUtility.UrlDecode(e.Marker.Text);
char[] delims = { '&' };
string[] Attribs = playerFeed.Split(delims);
foreach (String attrib in Attribs)
{
string[] keypair = attrib.Split('=');
string key = "";
string value = "";
try
{
key = keypair[0];
}
catch
{
key = null;
}
if (key != null)
{
try
{
value = keypair[1];
}
catch
{
value = "";
}
songAttribs.Add(keypair[0], keypair[1]);
}
}
nowplaying.Title = songAttribs["title"];
nowplaying.Artist = songAttribs["artist"];
nowplaying.Duration = 0;
this.label2.Content = "Artist: " + nowplaying.Artist;
this.label3.Content = "Title: " + nowplaying.Title;
this.label1.Content = playerFeed;
}
Still working on some of the code but so far things seem to be working.
Mayba WMP and WinAmp get the Informations from a Website or something like this, and dont read it out of the stream...
Werewolve

Categories