Microphone Audio Streaming from ESP8266 to C# Socket Server over wifi - arduino-uno

I want to stream the audio recorded by microphone on my ESP8266MOD to my C# Socket Program using UDP packets. But I'm getting analog outputs on every second. If I try to convert that signal to .wav file in my C# program it says that: "The wave header is corrupt.". Anyone have solution for this?
This is my Code for C# server:
public class UDPAudioListner
{
private const int listenPort = 12000;
public static int Main()
{
bool done = false;
UdpClient listener = new UdpClient(listenPort);
listener.DontFragment = true;
IPAddress ipAddress = IPAddress.Parse("192.168.1.145");
IPEndPoint groupEP = new IPEndPoint(ipAddress, listenPort);
byte[] receive_byte_array;
List<byte[]> masterByteList = new List<byte[]>();
byte[] bt = new byte[512];
int i = 44;
try
{
while (!done)
{
Console.WriteLine("Waiting for broadcast");
receive_byte_array = listener.Receive(ref groupEP);
Console.WriteLine("Received a broadcast from {0}", groupEP.ToString());
var data = "";
if (receive_byte_array.Length > 0)
{
try
{
using (Stream s = new MemoryStream(receive_byte_array))
{
s.Position = 0;
System.Media.SoundPlayer myPlayer = new System.Media.SoundPlayer(s);
myPlayer.Stream = null;
myPlayer.Stream = s;
myPlayer.Play();
bt = new byte[512];
i = 0;
}
}
catch (Exception ex)
{
done = false;
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
listener.Close();
return 0;
}
}
Here is my Arduino code:
void sendAudio(){
IPAddress ip(255, 255, 255, 122);
unsigned int localPort = 12000;
UdpSA.beginPacket(ip, localPort);
mic = analogRead(A0);
analogWrite(3,mic>> 2);
UdpSA.write(mic);
UdpSA.endPacket();
}

I would not recommend to stream audio via ESP8266.
The maximum rate of reading the analog input is 200 per second.
This means, that you can play the audio at a maximum of 200Hz.
Usual .wav files are need a minimum (I would recommend) of 8000Hz.
Good quality is achievable at 44100Hz.
I tried the same aproach as you did and all i got out of my speakers, were higher and lower noises.

Related

windows phone 7 Recording Issue

I will working on the Recording functionality in my windows phone 7 app.
I implemented the Recording functionality through this reference link.
It completely works fine at there and in my case also.
Actually the scenario is, In my application i created first page that will works as the recording screen as same as above referred link.
and when we stop the recording i redirected to the second page and saved that recording in Isolated storage and at the second page i bound the recorded sounds. At here i played the recorded sounds at it works fine.
Now, when i m again go to the recording screen(first page) and starts another recording. it will some times records fine and some times it will skip the some sounds during recording as like beep sounds and it will looks like a extra noise in recording and not getting properly recording sounds.
My Code is like,
public partial class NikhilRecord : PhoneApplicationPage
{
//XNA Objects for Record And Playback
Microphone mphone;
//Used for Storing captured buffers
List<byte[]> memobuffercollection = new List<byte[]>();
//Used for displaying stored memos
ObservableCollection<MemoInfo> memofiles = new ObservableCollection<MemoInfo>();
SpaceTime spaceTime = new SpaceTime();
public NikhilRecord()
{
InitializeComponent();
//Create new Microphone and set event handler.
mphone = Microphone.Default;
mphone.BufferReady += OnMicrophoneBufferReady;
String FileName = PhoneApplicationService.Current.State["MySelectedSong"].ToString();
using (IsolatedStorageFile IsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
try
{
using (IsolatedStorageFileStream fileStream = IsolatedStorage.OpenFile(FileName, FileMode.Open, FileAccess.Read))
{
MyMedia.SetSource(fileStream);
MyMedia.CurrentStateChanged += new RoutedEventHandler(mediaPlayer_CurrentStateChanged);
fileStream.Close();
fileStream.Dispose();
//Start Recording
OnRecordButtonClick();
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
}
void UpdateRecording(bool isRecording)
{
if (!isRecording)
{
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
spaceTime.Space = storage.AvailableFreeSpace;
}
}
else
{
spaceTime.Space = memobuffercollection.Count * mphone.GetSampleSizeInBytes(mphone.BufferDuration);
}
spaceTime.Time = mphone.GetSampleDuration((int)Math.Min(spaceTime.Space, Int32.MaxValue));
}
void OnMicrophoneBufferReady(object sender, EventArgs e)
{
// Get buffer from microphone and add to collection
byte[] buffer = new byte[mphone.GetSampleSizeInBytes(mphone.BufferDuration)];
int bytesreturned = mphone.GetData(buffer);
memobuffercollection.Add(buffer);
UpdateRecording(true);
// To be Continue...
if (spaceTime.Time > TimeSpan.FromMinutes(10))
{
StopRecording();
UpdateRecording(false);
}
}
void OnRecordButtonClick()
{
if (mphone.State == MicrophoneState.Stopped)
{
// Clear the collection for storing the buffers
memobuffercollection.Clear();
// Start Recording
mphone.Start();
MyMedia.Play();
}
else
{
MyMedia.Stop();
//mphone.Stop();
PopUpGrid.Visibility = Visibility.Visible;
RecordGrid.Opacity = 0.5;
RecordGrid.IsHitTestVisible = false;
}
bool isRecording = mphone.State == MicrophoneState.Started;
UpdateRecording(isRecording);
}
void StopRecording()
{
// Get the last partial buffer
int sampleSize = mphone.GetSampleSizeInBytes(mphone.BufferDuration);
byte[] extraBuffer = new byte[sampleSize];
int extraBytes = mphone.GetData(extraBuffer);
// Stop Recording
mphone.Stop();
//Stop the Song
MyMedia.Stop();
// Create MemoInfo object and add at top of collection
int totalSize = memobuffercollection.Count * sampleSize + extraBytes;
TimeSpan duration = mphone.GetSampleDuration(totalSize);
MemoInfo memoInfo = new MemoInfo(DateTime.UtcNow, totalSize, duration);
memofiles.Insert(0, memoInfo);
// Save Data in IsolatedStorage
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
string[] alldirectories = storage.GetDirectoryNames("NikDirectory");
if (alldirectories.Count() == 0)
storage.CreateDirectory("NikDirectory");
try
{
using (IsolatedStorageFileStream stream = storage.CreateFile("NikDirectory\\" + memoInfo.FileName))
{
// Write buffers from collection
foreach (byte[] buffer in memobuffercollection)
stream.Write(buffer, 0, buffer.Length);
// Write partial buffer
stream.Write(extraBuffer, 0, extraBytes);
stream.Close();
stream.Dispose();
}
Uri url = new Uri("/Gallery.xaml", UriKind.Relative);
NavigationService.Navigate(url);
memobuffercollection.Clear();
}
catch (Exception ees)
{
MessageBox.Show(ees.Message);
Uri url = new Uri("/Karaoke.xaml", UriKind.Relative);
NavigationService.Navigate(url);
}
}
bool isRecording = mphone.State == MicrophoneState.Started;
UpdateRecording(isRecording);
}
}
So, please help me out the problem. I heard at somewhere that you have to dispose all the objects of the microphone when you redirect to another screen. is it true ? or anything else.
Please help me.
Looking Forward.
Instead of using a collection, you should use following way to read your recorded bytes.
This should be done into the BufferReady event of your microphone object.
byte[] audioBuffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];
microphone.GetData(audioBuffer);
RecordingStream.Write(audioBuffer, 0, audioBuffer.Length);
RecordingStream is a MemoryStream , should be declared globally.
I am not sure about this but as I have used it and it works completely fine in each case.
Try this.

How can I find the IP address of connected network in windows phone?

I am trying to find the IP address of connected network in windows phone. I was successful to find out the IP address of connected Wi-Fi. I have used the following class to find the IP address.
public class MyIPAddress
{
Action<IPAddress> FoundCallback;
UdpAnySourceMulticastClient MulticastSocket;
const int PortNumber = 50000; // pick a number, any number
string MulticastMessage = "FIND-MY-IP-PLEASE" + new Random().Next().ToString();
public void Find(Action<IPAddress> callback)
{
FoundCallback = callback;
MulticastSocket = new UdpAnySourceMulticastClient(IPAddress.Parse("239.255.255.250"), PortNumber);
MulticastSocket.BeginJoinGroup((result) =>
{
try
{
MulticastSocket.EndJoinGroup(result);
GroupJoined(result);
}
catch (Exception ex)
{
// Debug.WriteLine("EndjoinGroup exception {0}", ex.Message);
// This can happen eg when wifi is off
FoundCallback(null);
}
},
null);
}
void callback_send(IAsyncResult result)
{
}
byte[] MulticastData;
bool keepsearching;
void GroupJoined(IAsyncResult result)
{
MulticastData = Encoding.UTF8.GetBytes(MulticastMessage);
keepsearching = true;
MulticastSocket.BeginSendToGroup(MulticastData, 0, MulticastData.Length, callback_send, null);
while (keepsearching)
{
try
{
byte[] buffer = new byte[MulticastData.Length];
MulticastSocket.BeginReceiveFromGroup(buffer, 0, buffer.Length, DoneReceiveFromGroup, buffer);
}
catch (Exception ex)
{
// Debug.WriteLine("Stopped Group read due to " + ex.Message);
keepsearching = false;
}
}
}
void DoneReceiveFromGroup(IAsyncResult result)
{
string str = "";
IPEndPoint where;
int responselength = MulticastSocket.EndReceiveFromGroup(result, out where);
byte[] buffer = result.AsyncState as byte[];
if (responselength == MulticastData.Length && buffer.SequenceEqual(MulticastData))
{
str = where.Address.ToString();
keepsearching = false;
FoundCallback(where.Address);
}
Console.WriteLine(str);
}
}
So by using the above class I can find the IP address of connected Wi-Fi. Now I am try to find the address of network which is connected by Data Connection. In my windows phone I goto Settings --> System --> Cellular and turn on data connection on.
How can I get the IP address of Cellular Network(Data Connection)? Is there any API for that?
you can try this ....
it will work fine for many networks unlike your code which will work only on wifi network due to multicast IP
it will provide you the ip address of the phone ...
public static IPAddress Find()
{
List<string> ipAddresses = new List<string>();
var hostnames = NetworkInformation.GetHostNames();
foreach (var hn in hostnames)
{
if (hn.IPInformation != null)
{
string ipAddress = hn.DisplayName;
ipAddresses.Add(ipAddress);
}
}
IPAddress address = IPAddress.Parse(ipAddresses[0]);
return address;
}

solution for OutOfMemoryExecption in silverlight

I'm creating an application in Silverlight that saves images in isolated storage.
I managed to save images in isolated storage but I'm having trouble by loading and displaying the image.
Here is the code:
public partial class MainPage : UserControl
{
private const string ImageName = "google1.png";
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
WriteableBitmap bitmap = new WriteableBitmap(saveImage, new TransformGroup());
loadedImage.Source = bitmap;
imageToStore(saveBuffer(bitmap), ImageName);
MessageBox.Show("saved");
}
public void imageToStore(byte[] buffer, string filename)
{
using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageFileStream s = new IsolatedStorageFileStream(filename, FileMode.Create, iso);
Int64 freeSpace = iso.AvailableFreeSpace;
Int64 needSpace = 20971520; // 20 MB in bytes
if (freeSpace < needSpace)
{
if (!iso.IncreaseQuotaTo(iso.Quota + needSpace))
{ MessageBox.Show("User rejected increase spacerequest");
}
else { MessageBox.Show("Space Increased");
}
}
using (StreamWriter writer = new StreamWriter(s))
{
writer.Write(buffer);
}
}
}
private static byte[] saveBuffer(WriteableBitmap bitmap)
{
long matrixSize = bitmap.PixelWidth * bitmap.PixelHeight;
long byteSize = matrixSize * 4 + 4;
byte[] retVal = new byte[byteSize];
long bufferPos = 0;
retVal[bufferPos++] = (byte)((bitmap.PixelWidth / 256) & 0xff);
retVal[bufferPos++] = (byte)((bitmap.PixelWidth % 256) & 0xff);
retVal[bufferPos++] = (byte)((bitmap.PixelHeight / 256) & 0xff);
retVal[bufferPos++] = (byte)((bitmap.PixelHeight % 256) & 0xff);
return retVal;
}
private void button2_Click(object sender, RoutedEventArgs e)
{
byte[] buffer = _LoadIfExists(ImageName);
loadedImage.Source = _GetImage(buffer);
MessageBox.Show("loaded");
}
private static byte[] _LoadIfExists(string fileName)
{
byte[] retVal;
using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
{
if (iso.FileExists(fileName))
{
using (IsolatedStorageFileStream stream = iso.OpenFile(fileName, FileMode.Open))
{
retVal = new byte[stream.Length];
stream.Read(retVal, 0, retVal.Length);
stream.Close();
}
}
else
{
retVal = new byte[0];
}
}
return retVal;
}
private static WriteableBitmap _GetImage(byte[] buffer)
{
int width = buffer[0] * 256 + buffer[1];
int height = buffer[2] * 256 + buffer[3];
long matrixSize = width * height;
//this is the section where Exception of type 'System.OutOfMemoryException' was thrown.
WriteableBitmap retVal = new WriteableBitmap(width, height);
int bufferPos = 4;
for (int matrixPos = 0; matrixPos < matrixSize; matrixPos++)
{
int pixel = buffer[bufferPos++];
pixel = pixel << 8 | buffer[bufferPos++];
pixel = pixel << 8 | buffer[bufferPos++];
pixel = pixel << 8 | buffer[bufferPos++];
retVal.Pixels[matrixPos] = pixel;
}
return retVal;
}}}
Hope you guys can help me. Thanks a lot.
Basically, use Silverlight to manage Image is not an easy task.
Whatever the power of the computer running your application, you are anyway limited by the browser, which by security will limit the RAM and processor dedicated to your application. (it will depend of the version of your browser, but it is roughly around 1Go of used RAM).
The only solution is to otpimize your memory management (always tricky in a managed language...):
Try to avoid your new instruction (reuse a maximum of object)
As soon as you do not need an object anymore, set its pointer to null (to keep it free to be collect by the garbage collector)
In a last option, try to call GC.Collect() in some strategic place (but be very carefull with that, your performance could dramatically decreased if you call it too often)

Windows Phone 7 - Upload file to FTP server

Hy.
I do an application in WP7 which is connet a FTP server. I would like to upload a photo(with photochoosertask).
I wrote a PhotoChooserTask() which I could choose a photo. The program save the photo name(samplephoto01.jpg) and the photo route.
And I wrote a code which send command to FTP server:
public static void Execute(String msg)
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
Byte[] cmd = Encoding.UTF8.GetBytes((msg + "\r\n").ToCharArray());
socketEventArg.SetBuffer(cmd, 0, cmd.Length);
socket.SendAsync(socketEventArg);
}
This code i can chose the photo:
public void SelectAndUpLoad()
{
PhotoChooserTask p = new PhotoChooserTask();
p.Completed += new EventHandler<PhotoResult>(pt_Completed);
p.ShowCamera = true;
p.Show();
}
void pt_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
BitmapImage img = new BitmapImage();
img.SetSource(e.ChosenPhoto);
MediaLibrary library = new MediaLibrary();
string PhotoPath = e.OriginalFileName;
// MessageBox.Show(PhotoPath);
for (int i = 0; i < library.Pictures.Count; i++)
{
Stream s = library.Pictures[i].GetImage();
if (s.Length == e.ChosenPhoto.Length)
{
string filename = library.Pictures[i].Name;
MessageBoxResult m = MessageBox.Show(filename, "Upload?", MessageBoxButton.OKCancel);
if (m == MessageBoxResult.OK)
{
Ftp.UploadFile(PhotoPath);
}
else
{
return;
}
break;
}
}
}
}
And this is the code whic i would like to upload the file:
public static void UploadFile(string file)
{
FileStream stream = new FileStream(file, FileMode.Open);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Execute("STRO " + file);
stream.Seek(0, SeekOrigin.Begin);
stream.Close();
}
But when i use the UploadFile(); method the program answer this:
MethodAccessException was unhandled
This code:
.
.
Ftp.UploadFile(PhotoPath);
}
else
{ //MethodAccessException
return;
}
break;
}
What was the wrong? Thank you!
I rewrote this code with IsolatedStorage to this:
for (int i = 0; i < library.Pictures.Count; i++)
{
Stream s = library.Pictures[i].GetImage();
if (s.Length == e.ChosenPhoto.Length)
{
string filename = library.Pictures[i].Name;
MessageBoxResult m = MessageBox.Show(filename, "Upload?", MessageBoxButton.OKCancel);
if (m == MessageBoxResult.OK)
{
IsolatedStorageFile iss = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream fs = iss.OpenFile(PhotoPath, FileMode.Open);
Ftp.UploadFile(fs, filename);
fs.Close();
}
else
{
return;
}
break;
}
}
And the UploadFile() method:
public static void UploadFile(IsolatedStorageFileStream file, string RemoteFile)
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
int bytes;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Execute("STRO " + RemoteFile);
file.Seek(0, SeekOrigin.Begin);
while ((bytes = file.Read(buffer, 0, buffer.Length)) > 0)
{
socketEventArg.SetBuffer(buffer, bytes, 0);
socket.SendAsync(socketEventArg);
}
}
But i get an exception in this source:
IsolatedStorageFileStream fs = iss.OpenFile(PhotoPath, FileMode.Open);
The exception is: IsolatedStorageException was unhadnled.
What is wrong?
I think your problem lies in the line:
FileStream stream = new FileStream(file, FileMode.Open);
You can't open files this way on WP7. To get a stream to a file, you can either open it from the Isolated Storage (given that the file is stored there), or use the stream provided by a built-in method.
In your case, you have the stream with the property e.ChosenPhoto. Why don't you use it directly?
public static void UploadFile(Stream stream, string file)
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Execute("STRO " + file);
stream.Seek(0, SeekOrigin.Begin);
stream.Close();
}
Then call UploadFile using e.ChosenPhoto as the first argument.

Lossless reading from mic

I'm using NAudio (but it applies to reading directly) to capture microphone wave data. It seems that if my app is busy it drops/skips some input data from the mic.
I've set the reading thread to top priority, but I'm doing heavy calculations in several other thread at the same time.
Is there a way to read data lossless?
(Or is it lossless, and my bug elsewhere?)
When I was making a similar app and had a similar problem, it turned out that I needed a buffer that can hold at least 3 seconds of data. Try to increase the buffer to 10 seconds of data and if it doesn't solve your problem then there are more issues. If it works try decreasing the buffer size until it works properly
EDIT: Here a quick & dirty managed dx recording for you to try.
public class BMSRecordingEventArgs : EventArgs
{
byte[] data;
bool endRec;
public BMSRecordingEventArgs(byte[] data, bool endRec)
{
this.data = data;
this.endRec = endRec;
}
public byte[] Data
{
get { return data; }
}
public bool EndRec
{
get { return endRec; }
}
}
public class AudioRecorder
{
public delegate void DataReceivedHandler(object sender, BMSRecordingEventArgs e);
public event DataReceivedHandler DataReceivedHandle;
public const int CAPTURE_BUFFER_SIZE = 32000;
DXS.Capture dxsCapDev;
DXS.CaptureBuffer dxsCapBuffer;
DXS.CaptureBufferDescription dxsCapBufferDesc;
System.Threading.Thread thrdCapturingThread;
DXS.BufferPositionNotify[] dxsBpna;
private volatile bool StopRec;
System.Threading.ManualResetEvent mreStillRunning = new System.Threading.ManualResetEvent(false);
DXS.BufferPositionNotify dxsBPNHalf;
DXS.BufferPositionNotify dxsBPNFull;
DXS.Notify Notify;
System.Threading.AutoResetEvent ARE;
public AudioRecorder(Guid DeviceGuid,DXS.WaveFormat wfWaveFormat,DXS.CaptureEffectDescription[] dxsCapEffectDesc)
{
dxsCapDev = new Microsoft.DirectX.DirectSound.Capture(DeviceGuid);
dxsCapBufferDesc = new Microsoft.DirectX.DirectSound.CaptureBufferDescription();
dxsCapBufferDesc.BufferBytes = CAPTURE_BUFFER_SIZE;
dxsCapBufferDesc.Format = wfWaveFormat;
dxsCapBufferDesc.WaveMapped = true;
dxsCapBufferDesc.CaptureEffectDescription = dxsCapEffectDesc;
dxsCapBufferDesc.ControlEffects = true;
dxsCapBuffer = new Microsoft.DirectX.DirectSound.CaptureBuffer(dxsCapBufferDesc, dxsCapDev);
ARE = new System.Threading.AutoResetEvent(false);
dxsBPNHalf = new Microsoft.DirectX.DirectSound.BufferPositionNotify();
dxsBPNFull = new Microsoft.DirectX.DirectSound.BufferPositionNotify();
dxsBPNHalf.Offset = CAPTURE_BUFFER_SIZE / 2 - 1;
dxsBPNFull.Offset = CAPTURE_BUFFER_SIZE-1;
dxsBPNFull.EventNotifyHandle = ARE.SafeWaitHandle.DangerousGetHandle();
dxsBPNHalf.EventNotifyHandle = ARE.SafeWaitHandle.DangerousGetHandle();
dxsBpna = new Microsoft.DirectX.DirectSound.BufferPositionNotify[2];
dxsBpna[0] = dxsBPNHalf;
dxsBpna[1] = dxsBPNFull;
Notify = new Microsoft.DirectX.DirectSound.Notify(dxsCapBuffer);
Notify.SetNotificationPositions(dxsBpna);
}
public void StartRecording()
{
if (thrdCapturingThread != null)
throw new Exception("Already Recording !");
StopRec = false;
thrdCapturingThread = new System.Threading.Thread(Record);
thrdCapturingThread.Start();
}
private void Record()
{
DataReceivedHandler drh2 = DataReceivedHandle;
dxsCapBuffer.Start(true);
byte[] TempBaf = new byte[CAPTURE_BUFFER_SIZE / 2];
int StartingOffset = 0;
while (dxsCapBuffer.Capturing && !StopRec)
{
ARE.WaitOne(-1,false);
StartingOffset %= CAPTURE_BUFFER_SIZE;
TempBaf = (byte[])dxsCapBuffer.Read(StartingOffset, typeof(byte), Microsoft.DirectX.DirectSound.LockFlag.FromWriteCursor, CAPTURE_BUFFER_SIZE / 2);
StartingOffset += TempBaf.Length;
if (drh2 != null)
drh2(this, new BMSRecordingEventArgs(TempBaf, false));
}
dxsCapBuffer.Stop();
if (drh2 != null)
drh2(this, new BMSRecordingEventArgs(TempBaf, true));
mreStillRunning.Set();
}
public void StopRecording()
{
StopRec = true;
mreStillRunning.WaitOne(-1,false);
thrdCapturingThread = null;
}
}

Resources