NAudio record never receiving a sample - c#

I'm attempting the simplest possible NAudio example to record from an input device but for some reason I can't get the DataAvailable callback function to be called.
In the example below a break point on Do Something never gets hit.
WaveIn waveIn = new WaveIn();
waveIn.DeviceNumber = 0;
waveIn.DataAvailable += waveIn_DataAvailable;
waveIn.RecordingStopped += new EventHandler(waveIn_RecordingStopped);
waveIn.WaveFormat = new WaveFormat(44100, 1);
waveIn.StartRecording();
private void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
Do Something
}
I've checked, re-checked and re-re-checked that the settings are exactly the same as those used by the NAudio VoiceRecorder test application which is able to record audio fine with the exact same settings.
The only difference is my test application is a console application rather than a WPF app. Would that make a difference?

Yes, it is because it is a console app, and the WaveIn class uses Windows messages as callbacks. If you are able to download and build the very latest source code from codeplex, you can use the brand new WaveInEvent class (added 6 Mar 2012), which does not rely on a Windows message loop.
Alternatively, if you are familiar with installing pre-release packages using NuGet, you can install the latest NAudio prerelease (currently 1.5.4-beta) which has this class in.

Just a thought, have you verified your device is valid?
Try something like this;
int waveInDevices = WaveIn.DeviceCount;
for (int waveInDevice = 0; waveInDevice < waveInDevices; waveInDevice++)
{
WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
MessageBox.Show("Device " + waveInDevice + ": " + deviceInfo.ProductName +
", " + deviceInfo.Channels + " channels");
}
to verify you have a recording device.

Related

Running Powershell script causes 'Memory corruption' or 'Cannot Read or Write'

Im making a program that makes a Wi-Fi hotspot for you and enables Internet Connection Sharing automaticly using a powershell script.
The script works and runs perfectly, but i have to wait for it to be finished so i can notify the user its done. Im using below code which works but...
but it crashes and causes an error on my home computer which is allot faster.
I get a Cannot read or write or memory is corrupt error which i can't really explain.
public static void ToggleIcs(string connectionInterface, bool state)
{
string toggle;
string par1;
string par2;
if (state){
toggle = "EnableSharing";
par1 = "0";
par2 = "1";
}else{
toggle = "DisableSharing";
par1 = "";
par2 = "";
}
using (PowerShell powerShellInstance = PowerShell.Create())
{
// this script enables or disables internet sharing with the connectionInterface given.
powerShellInstance.AddScript("" +
"regsvr32 hnetcfg.dll /s;" +
"$m = New-Object -ComObject HNetCfg.HNetShare;" +
"$m.EnumEveryConnection |% { $m.NetConnectionProps.Invoke($_) };" +
"$c = $m.EnumEveryConnection |? { $m.NetConnectionProps.Invoke($_).Name -eq '" + connectionInterface + "' };" +
"$config = $m.INetSharingConfigurationForINetConnection.Invoke($c);" +
"Write-Output $config.SharingEnabled;" +
"Write-Output $config.SharingConnectionType;" +
"$config." + toggle + "(" + par1 + ");" +
"$m2 = New-Object -ComObject HNetCfg.HNetShare;" +
"$m2.EnumEveryConnection |% { $m2.NetConnectionProps.Invoke($_) };" +
"$c2 = $m2.EnumEveryConnection |? { $m2.NetConnectionProps.Invoke($_).DeviceName -Match 'Microsoft Hosted Network Virtual Adapter' };" +
"$config2 = $m2.INetSharingConfigurationForINetConnection.Invoke($c2);" +
"Write-Output $config2.SharingEnabled;" +
"Write-Output $config2.SharingConnectionType;" +
"$config." + toggle + "(" + par2 + ");");
PSDataCollection<PSObject> outputCollection = new PSDataCollection<PSObject>();
IAsyncResult result = powerShellInstance.BeginInvoke<PSObject, PSObject>(null, outputCollection);
Console.WriteLine(DateTime.Now + ">> Started Powershell script");
int i = 0;
while (!result.IsCompleted)
{
if (i < 60)
{
Console.WriteLine(DateTime.Now + ">> Running script");
}
else
{
ScriptFailed();
powerShellInstance.Stop();
break;
}
i++;
Thread.Sleep(1000);
}
Console.WriteLine(DateTime.Now + ">> Executed Internet Sharing script");
}
}
This is the error im getting:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I don't get a line that says where it crashes but it crashes after Thread.Sleep(1000);. Which i found out using breakpoints
As I said, the script runs fine on my laptop, and it does work on my faster computer, but it crashes as soon as it hits Thread.Sleep(1000).
After it crashed, I checked if ICS was enabled in the network and sharing center, and and it did so correctly.
I tried removing the Thread.Sleep(1000); but then it crashes anyway a line before.
What can I try or do differently?
Edit
i dont have the stack trace yet, as i am not on my faster PC where it crashes. but I will post it as soon as possible.
Edit
As mentioned by TheLethalCoder, it could be that i try to acces IsCompleted While it is being updated. If that is why it happens, How would I check if it is being altered or wait for it to be done.
Edit
As i dont really know what the call stack is for, or what a stack trace is, and how i can use it ill provide an image of what i saw one moment before the crash.
Edit
I did some snooping around and found a few things i tried.
first, in the application properties -> build, i ticked "Prefer 32bit" off
Because some people fixed their problems with this. And i did not get a crash but the script also failed to run and caused my internet connection to drop.
so i turned it back on.
I also tried the netsh winsock reset command and restarting my pc but it still crashed.
Im all out of clues now, but i posted these two things for people who come by looking for an answer and maybe this will work.
The MSDN article: Polling for the Status of an Asynchronous Operation states that the way you are polling the result is correct. However their example doesn't include a Thread.Sleep:
while (result.IsCompleted != true)
{
UpdateUserInterface();
}
So to eliminate this I would use the following snippet that keeps track of the variables without sleeping, note that printing to the Console on every loop is going to quickly pollute the window though:
Stopwatch sw = new Stopwatch();
sw.Start();
while (!result.IsCompleted)
{
if (sw.EllapsedMilliseconds >= 60000) //60 seconds
{
break;
}
Console.WriteLine(DateTime.Now + ">> Running script");
}
if (!result.IsCompleted)
{
ScriptFailed();
powerShellInstance.Stop();
}
This is more of a comment than an answer but it was getting too long to be used as a comment.

Using C# and Netduino to log data

I am developing a telemetry platform for a nano-printing project. My team is using a Netduino 2 plus (not my first choice, but what are you going to do?) I am not at all familiar with C# and am a novice programmer, to be certain.
We have some code written that successfully polls an I2C temperature sensor and uses debug.print to write to the console. I would like this data written to a file, instead.
There are examples out there to transfer files from the SD card to a PC, but this seems unnecessary to me (though it may be completely necessary in order to not overrun the buffer?). Is there a call that will simply write the data to a file instead of writing to the console?
It is my understanding that we may need an application to listen to the serial port on the PC. It seems we would also need a corresponding application to write from the hardware. I've used microcontrollers in the past that simply open a serial and send over USB to a file location.
Here is the code we are using to print the data to the console:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using System.IO.Ports;
namespace NetduinoApplication1
{
public class Program
{
public static void Main()
{
OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
OutputPort p = new OutputPort(Pins.GPIO_PIN_SDA, true);
p.Write(false);
p.Dispose();
// write your code here
byte[] Addr = new byte[1];
Addr[0] = 0x07;
byte[] TxBuff = new byte[9];
byte[] RxBuff = new byte[9];
I2CDevice.Configuration I2C_Configuration = new I2CDevice.Configuration(0x5A, 100);
I2CDevice I2C1 = new I2CDevice(I2C_Configuration);
I2CDevice.I2CTransaction[] WriteTran = new I2CDevice.I2CTransaction[] { I2CDevice.CreateWriteTransaction(Addr), I2CDevice.CreateWriteTransaction(TxBuff) };
I2CDevice.I2CTransaction[] ReadTran = new I2CDevice.I2CTransaction[] { I2CDevice.CreateWriteTransaction(Addr), I2CDevice.CreateReadTransaction(RxBuff) };
while (true)
{
int iWriteCount = I2C1.Execute(WriteTran, 1000);
//Debug.Print("Write Count: " + iWriteCount.ToString());
led.Write(true);
Thread.Sleep(200);
int iReadCount = I2C1.Execute(ReadTran, 1000);
if (iReadCount >= 2)
{
int iVal = RxBuff[1] * 256 + RxBuff[0];
double Temperature = ((iVal * 0.02) - 273.15) * 9.0 / 5.0 + 32.0;
Debug.Print("Temperature: " + Temperature.ToString() + " deg F");
}
led.Write(false);
Thread.Sleep(200);
}
}
}
}
If I need to create an application, I'd like to do it, but I could really use some direction. A little experience here would go a long way.
So, a couple things come to mind.
If your Netduino has network connectivity, you could write data to a file on the SD card and then transfer the file out via FTP. There are plenty of libraries to do this with.
Same as 1, except push the data to a web service. There is an HTTPRequest library you could use to do up a quick JSON post to a web service. You would need to write the web service. But there are also plenty of free services out there that will take data feeds and store them like ubidots.
If you really want to go the serial port route, the bad news is that the Netduino's USB Serial port is reserved for debugging. But you can get a cheap little USB UART adapter to do this. There is a great blog post here that explains it.
Good Luck!

Enumerate available WiFi Printers in my Windows Phone app

I know similar questions have been asked a lot, ie "can I print from my wp8?". Most folks seem content with the simple "no" response. I am looking to add this functionality into my app and I know it can be accomplished at some level - even if I can only support a very minimum printer set for now.
I've looked at the app PrintHand, and it appears to have the capabilities I need: print to wireless and Bluetooth printers.
I've been looking through the Bluetooth scenarios document a bit and I think this might help discover a Bluetooth printer. That's a start. Perhaps it will help in identifying wireless printers also.
I realize I need to start very small with this project and I want to first try to enumerate any wireless printers (I don't have a Bluetooth one yet) available on the current network. Would anybody happen to have a pointer in the right direction on how to get started or better yet, some related sample code?
Thanks so much!
Best I can give is my Github Repo which isn't related to Wifi printers, but Google cloud printing.
There isn't really a .net reference for using Google Cloud Print in their documentation, but the code works in Mono, and should be easy to move over to .NET and hence, Windows Phone.
MonoGCP
I was able to detect a nearby wireless printer using Simple Service Discovery Protocol.
Here is my sample function:
private const string SSDP_IP = "239.255.255.250";
private const string SSDP_PORT = "1900";
public async static void DiscoverAsync2()
{
var multicastIP = new HostName(SSDP_IP);
var found = false;
using (var socket = new DatagramSocket())
{
socket.MessageReceived += (sender, e) =>
{
var reader = e.GetDataReader();
var bytesRemaining = reader.UnconsumedBufferLength;
var receivedString = reader.ReadString(bytesRemaining);
// TODO: something useful with this new info
found = true;
};
await socket.BindEndpointAsync(null, string.Empty);
socket.JoinMulticastGroup(multicastIP);
while (true)
{
found = false;
using (var stream = await socket.GetOutputStreamAsync(multicastIP, SSDP_PORT))
{
var request = new StringBuilder();
request.AppendLine("M-SEARCH * HTTP/1.1");
request.AppendLine("HOST: " + SSDP_IP + ":" + SSDP_PORT);
request.AppendLine("MAN: \"ssdp:discover\"");
request.AppendLine("MX: 3");
request.AppendLine("ST: urn:schemas-upnp-org:device:Printer:1"); // use ssdp:all to get everything
request.AppendLine(); // without this extra blank line, query won't run properly
var buff = Encoding.UTF8.GetBytes(request.ToString());
await stream.WriteAsync(buff.AsBuffer());
await Task.Delay(5000);
if (!found)
break;
}
}
}

Media player in Windows Phone 7

I am using the media player in Windows Phone 7 to play the music in the phone song collection. But when it play the music they will be an exception and the error is stating
FrameworkDispatcher.Update has not been called. Regular FrameworkDispatcher.Update calls are necessary for fire and forget sound effects and framework events to function correctly.
How should i go about modifying my code?
private void songBtn_Click(object sender, RoutedEventArgs e)
{
using (var ml = new MediaLibrary())
{
foreach (var song in ml.Songs)
{
System.Diagnostics.Debug.WriteLine(song.Artist + " " + song.Name);
MessageBox.Show(song.Artist + " " + song.Name);
}
MediaPlayer.Play(ml.Songs[0]);
}
}
You have to call
FrameworkDispatcher.Update()
whenever you make a call to an XNA media library
so your code should look like this
using (var ml = new MediaLibrary())
{
foreach (var song in ml.Songs)
{
System.Diagnostics.Debug.WriteLine(song.Artist + " " + song.Name);
MessageBox.Show(song.Artist + " " + song.Name);
}
FrameworkDispatcher.Update();
MediaPlayer.Play(ml.Songs[0]);
}
The error is occouring because you're using the XNA Framework in a regular Windows Phone 7 application.
If you read the error description, you would gotten this link to MSDN: Enable XNA Framework Events in Windows Phone Applications , which explains precisely what to do.

Hostname scanning in C#

Iv'e recently started a new job as an ICT Technician and im creating an Console application which will consists of stuff that will help our daily tools!
My first tool is a Network Scanner, Our system currently runs on Vanilla and Asset tags but the only way we can find the hostname / ip address is by going into the Windows Console tools and nslookup which to me can be improved
I want to create an application in which I enter a 6 digit number and the application will search the whole DNS for a possible match!
Our hostsnames are like so
ICTLN-D006609-edw.srv.internal the d 006609 would be the asset tag for that computer.
I wish to enter that into the Console Application and it search through every hostname and the ones that contain the entered asset tag within the string will be returned along with an ip and full computer name ready for VNC / Remote Desktop.
Firstly how would I go about building this, shall i start the project of as a console app or a WPF. can you provide an example of how I can scan the hostnames via C#, or if there's an opensource C# version can you provide a link.
Any information would be a great help as it will take out alot of issues in the workpalce as we have to ask the customer to go into there My Computer adn properties etc and then read the Computer name back to use which I find pointless.
Regards.
Updates:
*1 C# Version I made: http://pastebin.com/wBWxyyuh
I would actually go about this with PowerShell, since automating tasks is kinda its thing. In fact, here's a PowerShell script to list out all computers visible on the network. This is easily translatable into C# if you really want it there instead.
function Find-Computer( [string]$assetTag ) {
$searcher = New-Object System.DirectoryServices.DirectorySearcher;
$searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry;
$searcher.SearchScope = 'Subtree';
$searcher.PageSize = 1000;
$searcher.Filter = '(objectCategory=computer)';
$results = $searcher.FindAll();
$computers = #();
foreach($result in $results) {
$computers += $result.GetDirectoryEntry();
}
$results.Dispose(); #Explicitly needed to free resources.
$computers |? { $_.Name -match $assetTag }
}
Here's a way you can accomplish this, although it's not the best. You might consider hitting Active Directory to find the legitimate machines on your network. The code below shows how you might resolve a machine name, and shows how to ping it:
static void Main()
{
for (int index = 0; index < 999999; index++)
{
string computerName = string.Format("ICTLN-D{0:000000}-edw.srv.internal", index);
string fqdn = computerName;
try
{
fqdn = Dns.GetHostEntry(computerName).HostName;
}
catch (SocketException exception)
{
Console.WriteLine(">>Computer not found: " + computerName + " - " + exception.Message);
}
using (Ping ping = new Ping())
{
PingReply reply = ping.Send(fqdn);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine(">>Computer is alive: " + computerName);
}
else
{
Console.WriteLine(">>Computer did not respond to ping: " + computerName);
}
}
}
}
Hope that helps...

Categories