Передача звука по сети по протоколу UDP (FullDuplex)
05.04.2012, 20:35. Показов 10116. Ответов 9
Здравствуйте.
Пишется программа по передачи различной информации по сети.
Вот дошло дело до звука...
Сначала был написан пробный код на Borland С++, вот он :
Клиент - воспроизводит полученный звук на динамик
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
| #include <vcl.h>
#include <stdio.h>
#pragma hdrstop
#include "FormMain.h"
//-----------------
#include <mmsystem.h>
#include <mmreg.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
//---------------------------------------------------------------------------
WAVEFORMATEX WavFormat;
WAVEHDR WavHdr[16];
HWAVEOUT Out;
unsigned int BufferSize;
short CurrentBufferNum = 0;
short BuffersCount = 8;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
}
//================================================================================
void SaveExceptionToFile(char *msg, ... )
{
AnsiString asErrorLogFileName = "MicServer.dat";
HANDLE hErrorLogFile;
DWORD SendBytes;
AnsiString asFileName = ExtractFilePath(ParamStr(0)) + asErrorLogFileName;
char ErrorStr[1024];
va_list ap;
memset(ErrorStr,0,sizeof(ErrorStr));
va_start( ap, msg ); vsprintf( ErrorStr, msg, ap ); va_end( ap );
if( strlen(ErrorStr) == 0 )
return;
hErrorLogFile = CreateFile(asFileName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS , 0, NULL );
SetFilePointer(hErrorLogFile,0,NULL,FILE_END);
WriteFile(hErrorLogFile,ErrorStr,StrLen(ErrorStr),&SendBytes,NULL);
CloseHandle(hErrorLogFile);
return;
}
//================================================================================
void PlayBuffer(TStream &Stream)
{
while(CurrentBufferNum != BuffersCount)
{
if(WavHdr[CurrentBufferNum].dwUser == 0)
{
Stream.Read(WavHdr[CurrentBufferNum].lpData,BufferSize);
waveOutPrepareHeader(Out,&WavHdr[CurrentBufferNum],sizeof(WavHdr));
waveOutWrite(Out,&WavHdr[CurrentBufferNum],sizeof(WavHdr));
WavHdr[CurrentBufferNum].dwFlags = 0;
WavHdr[CurrentBufferNum].dwBufferLength = BufferSize;
WavHdr[CurrentBufferNum].dwBytesRecorded = 0;
WavHdr[CurrentBufferNum].dwUser = 0;
WavHdr[CurrentBufferNum].dwLoops = 1;
WavHdr[CurrentBufferNum].dwFlags = WHDR_INQUEUE;
CurrentBufferNum ++;
return;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
int i;
int Res;
WavFormat.wFormatTag = WAVE_FORMAT_PCM;
WavFormat.nChannels = 1;
WavFormat.wBitsPerSample = 8;
WavFormat.nBlockAlign = 1;
WavFormat.nSamplesPerSec = 8000;
WavFormat.nAvgBytesPerSec = WavFormat.nSamplesPerSec * WavFormat.nBlockAlign;
WavFormat.cbSize = 0;
BufferSize = (WavFormat.nAvgBytesPerSec*2)/16;
for(i=0;i<BuffersCount;i++)
{
WavHdr[i].dwFlags = WHDR_INQUEUE;
WavHdr[i].dwBufferLength = BufferSize;
WavHdr[i].dwBytesRecorded = 0;
WavHdr[i].dwUser = 0;
WavHdr[i].dwLoops = 1;
WavHdr[i].lpData = StrAlloc(BufferSize);//(char *)GlobalAlloc(GMEM_FIXED,BufferSize);
}
Res = waveOutOpen(&Out,0/*WAVE_MAPPER*/,&WavFormat,(DWORD)MainForm->Handle,0,CALLBACK_WINDOW);
if(Res != MMSYSERR_NOERROR)
{
Application->MessageBoxA("Error OutOpen", 0);
}
IdUDPServer->BufferSize = BufferSize;
IdUDPServer->DefaultPort = 10090;
IdUDPServer->Active = false;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action)
{
IdUDPServer->Active = false;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button1Click(TObject *Sender)
{
IdUDPServer->Active = !IdUDPServer->Active;
if(IdUDPServer->Active == false)
Button1->Caption = "Off";
else
Button1->Caption = "On";
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::IdUDPServerUDPRead(TObject *Sender, TStream *AData, TIdSocketHandle *ABinding)
{
if(CurrentBufferNum == BuffersCount)
CurrentBufferNum = 0;
PlayBuffer(*AData);
}
//--------------------------------------------------------------------------- |
|
Сервер - снимает звук с микрофона и передает клиенту
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
| #include <vcl.h>
#include <stdio.h>
//-----------------
#include <mmsystem.h>
#include <mmreg.h>
//-----------------
#pragma hdrstop
#include "FormMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
//----------------------------------
WAVEFORMATEX WavFormat;
WAVEHDR WavHdr;
HWAVEIN In;
unsigned int BufferSize;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
}
//================================================================================
void SaveExceptionToFile(char *msg, ... )
{
AnsiString asErrorLogFileName = "MicServer.dat";
HANDLE hErrorLogFile;
DWORD SendBytes;
AnsiString asFileName = ExtractFilePath(ParamStr(0)) + asErrorLogFileName;
char ErrorStr[1024];
va_list ap;
memset(ErrorStr,0,sizeof(ErrorStr));
va_start( ap, msg ); vsprintf( ErrorStr, msg, ap ); va_end( ap );
if( strlen(ErrorStr) == 0 )
return;
hErrorLogFile = CreateFile(asFileName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS , 0, NULL );
SetFilePointer(hErrorLogFile,0,NULL,FILE_END);
WriteFile(hErrorLogFile,ErrorStr,StrLen(ErrorStr),&SendBytes,NULL);
CloseHandle(hErrorLogFile);
return;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
int Res;
WavFormat.wFormatTag = WAVE_FORMAT_PCM;
WavFormat.nChannels = 1;
WavFormat.wBitsPerSample = 8;
WavFormat.nBlockAlign = 1;
WavFormat.nSamplesPerSec = 8000;
WavFormat.nAvgBytesPerSec = WavFormat.nSamplesPerSec * WavFormat.nBlockAlign;
WavFormat.cbSize = 0;
BufferSize = (WavFormat.nAvgBytesPerSec*2)/16;
Res = waveInOpen(&In,0/*WAVE_MAPPER*/,&WavFormat,(DWORD)MainForm->Handle,0,CALLBACK_WINDOW);
if(Res != MMSYSERR_NOERROR)
{
Application->MessageBoxA("Error InOpen", 0);
}
WavHdr.lpData = (char *)GlobalAlloc(GMEM_FIXED,BufferSize);
WavHdr.dwBufferLength = BufferSize;
WavHdr.dwFlags = 0;
IdUDPClient->BufferSize = BufferSize;
IdUDPClient->Port = 10090;
IdUDPClient->Active = false;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action)
{
IdUDPClient->Active = false;
waveInClose(In);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::WavMessage(TMessage &Msg)
{
waveInPrepareHeader(In,&WavHdr,sizeof(WavHdr));
waveInAddBuffer(In,&WavHdr,sizeof(WavHdr));
IdUDPClient->SendBuffer(WavHdr.lpData,WavHdr.dwBufferLength);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button1Click(TObject *Sender)
{
if(IdUDPClient->Active == false)
{
Button1->Caption = "Stop";
IdUDPClient->Host = Edit1->Text;
waveInPrepareHeader(In,&WavHdr,sizeof(WavHdr));
waveInAddBuffer(In,&WavHdr,sizeof(WavHdr));
IdUDPClient->Active = true;
waveInStart(In);
}
else
{
Button1->Caption = "Start";
IdUDPClient->Active = false;
waveInUnprepareHeader(In,&WavHdr,sizeof(WavHdr));
waveInStop(In);
}
} |
|
Все прекрасно работает.
Но так как основная программа пишется на С# был вынужден написать следующие:
Библbотека SoundLib
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
| using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
//----------------------------------------------
//using Microsoft.DirectX;
using Microsoft.DirectX.AudioVideoPlayback;
//----------------------------------------------
using System.Runtime.InteropServices;
//----------------------------------------------
namespace SoundLib
{
public class Sound : IDisposable
{
#region ----- Constant -----
public const uint WAVE_MAPPER = unchecked((uint)(-1));
public const int MMSYSERR_NOERROR = 0;
public const int MM_WOM_OPEN = 0x3BB;
public const int MM_WOM_CLOSE = 0x3BC;
public const int MM_WOM_DONE = 0x3BD;
public const int MM_WIM_OPEN = 0x3BE;
public const int MM_WIM_CLOSE = 0x3BF;
public const int MM_WIM_DATA = 0x3C0;
public const int CALLBACK_FUNCTION = 0x00030000;
public const int CALLBACK_WINDOW = 0x00010000;
public const int CALLBACK_TASK = 0x00020000;
public const int CALLBACK_EVENT = 0x00050000;
public const int TIME_MS = 0x0001;
public const int TIME_SAMPLES = 0x0002;
public const int TIME_BYTES = 0x0004;
#endregion
#region ----- Validation ------
// ---------------------- Кулбак --------------------------------------
public delegate void WaveCallbackProc(IntPtr hwi, WimMessageType uMsg, IntPtr dwInstance, IntPtr dwParam1, IntPtr dwParam2);
//--------------------------
public static Audio AudioPlayer;
public static string[] InDeviceName;
public static string[] OutDeviceName;
public static byte InDeviceCount;
public static byte OutDeviceCount;
public static IntPtr hWaveIn;
public static IntPtr hWaveOut;
public static WAVEFORMATEX waveFormat;
public static WAVEHDR waveInHeader;
public static WAVEHDR[] waveOutHeader = new WAVEHDR[16];
public static int BufferSize = 0;
//----------------
public static short CurrentBufferNum = 0;
public static short BuffersCount = 8;
#endregion
#region ----- Enums -----
public enum WimMessageType : uint
{
OpenIn = 0x3BE,
CloseIn = 0x3BF,
DataIn = 0x3C0,
OpenOut = 0x3BB,
CloseOut = 0x3BC,
DataOut = 0x3BD
}
public enum SoundState : byte
{
None = 1,
Present,
Ring,
Call,
WaitAnswerOnCommand,
Start,
Stop
}
#endregion
#region ----- Struct ------
[StructLayout( LayoutKind.Sequential )]
public struct WAVEHDR
{
public IntPtr lpData;
public int dwBufferLength;
public int dwBytesRecorded;
public IntPtr dwUser;
public int dwFlags;
public int dwLoops;
public IntPtr lpNext;
public IntPtr reserved;
}
[StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
public struct WAVEINCAPS
{
public short wMid;
public short wPid;
public uint vDriverVersion;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 128 )]
public string szPname;
public uint dwFormats;
public short wChannels;
public short wReserved1;
public uint dwSupport;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WAVEOUTCAPS
{
public short wMid;
public short wPid;
public uint vDriverVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szPname;
public uint dwFormats;
public short wChannels;
public short wReserved1;
public uint dwSupport;
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct WAVEFORMATEX
{
public ushort FormatTag;
public ushort Channels;
public uint SamplesPerSecond;
public uint AverageBytesPerSecond;
public ushort BlockAlign;
public ushort BitsPerSample;
public ushort Size;
}
[StructLayout(LayoutKind.Sequential)]
public struct smpte
{
public byte hour; /* hours */
public byte min; /* minutes */
public byte sec; /* seconds */
public byte frame; /* frames */
public byte fps; /* frames per second */
public byte dummy; /* pad */
public ushort pad;
}
[StructLayout(LayoutKind.Explicit)]
public struct MMTIME
{
[FieldOffset(0)]
public uint wType; /* indicates the contents of the union */
[FieldOffset(4)]
public uint ms; /* milliseconds */
[FieldOffset(4)]
public uint sample; /* samples */
[FieldOffset(4)]
public uint cb; /* byte count */
[FieldOffset(4)]
public uint ticks; /* ticks in MIDI stream */
[FieldOffset(4)]
public smpte smpte;
[FieldOffset(4)]
public uint songptrpos; /* song pointer position */
}
#endregion
#region ----- Share API from winmm.dll -----
const string WINMM = "winmm.dll";
#region ----- WaveOut -----
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutGetNumDevs();
[DllImport(WINMM, SetLastError = true, CharSet = CharSet.Unicode)] public static extern int waveOutGetDevCaps(UIntPtr uDeviceID, out WAVEOUTCAPS lpCaps, int uSize);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutPrepareHeader(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, int uSize);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutUnprepareHeader(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, int uSize);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutWrite(IntPtr hWaveOut, ref WAVEHDR lpWaveOutHdr, int uSize);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutOpen(ref IntPtr hWaveOut, int DeviceID, ref WAVEFORMATEX lpFormat, IntPtr dwCallback, IntPtr dwInstance, uint dwFlags);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutReset(IntPtr hWaveOut);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutClose(IntPtr hWaveOut);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutPause(IntPtr hWaveOut);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutRestart(IntPtr hWaveOut);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutGetPosition(IntPtr hWaveOut, out MMTIME lpInfo, int uSize);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutSetVolume(IntPtr hWaveOut, uint dwVolume);
[DllImport(WINMM, SetLastError = true)] public static extern int waveOutGetVolume(IntPtr hWaveOut, out uint dwVolume);
#endregion
#region ----- WaveIn -----
[DllImport(WINMM, SetLastError = true)] public static extern int waveInGetNumDevs();
[DllImport(WINMM, SetLastError = true, CharSet = CharSet.Unicode)] public static extern int waveInGetDevCaps(UIntPtr uDeviceID, out WAVEINCAPS lpCaps, int uSize);
[DllImport(WINMM, SetLastError = true)] public static extern int waveInAddBuffer(IntPtr hwi, ref WAVEHDR pwh, int cbwh);
[DllImport(WINMM, SetLastError = true)] public static extern int waveInClose(IntPtr hwi);
[DllImport(WINMM, SetLastError = true)] public static extern int waveInOpen(ref IntPtr hWaveIn, int deviceId, ref WAVEFORMATEX wfx, IntPtr dwCallback, IntPtr dwInstance, uint dwFlags);
[DllImport(WINMM, SetLastError = true)] public static extern int waveInPrepareHeader(IntPtr hWaveIn, ref WAVEHDR lpWaveInHdr, int uSize);
[DllImport(WINMM, SetLastError = true)] public static extern int waveInUnprepareHeader(IntPtr hWaveIn, ref WAVEHDR lpWaveInHdr, int uSize);
[DllImport(WINMM, SetLastError = true)] public static extern int waveInReset(IntPtr hwi);
[DllImport(WINMM, SetLastError = true)] public static extern int waveInStart(IntPtr hwi);
[DllImport(WINMM, SetLastError = true)] public static extern int waveInStop(IntPtr hwi);
#endregion
#endregion
#region -------------------------- Main Init Sound Function -------------------------------
public static void InitSound()
{
int i;
try
{
//------------------ In
if ((InDeviceCount = (byte)waveInGetNumDevs()) > 0)
{
InDeviceName = new string[InDeviceCount];
var waveInCaps = new WAVEINCAPS();
int size = Marshal.SizeOf(waveInCaps);
for (i = 0; i < InDeviceCount; i++)
{
if (waveInGetDevCaps((UIntPtr)i, out waveInCaps, size) == MMSYSERR_NOERROR)
InDeviceName[i] = waveInCaps.szPname;
}
}
//---------------- Out
if ((OutDeviceCount = (byte)waveOutGetNumDevs()) > 0)
{
OutDeviceName = new string[OutDeviceCount];
var waveOutCaps = new WAVEOUTCAPS();
int size = Marshal.SizeOf(waveOutCaps);
for (i = 0; i < OutDeviceCount; i++)
{
if (waveOutGetDevCaps((UIntPtr)i, out waveOutCaps, size) == MMSYSERR_NOERROR)
OutDeviceName[i] = waveOutCaps.szPname;
}
}
waveFormat.FormatTag = 1;
waveFormat.Channels = 1;
waveFormat.BitsPerSample = 8;
waveFormat.SamplesPerSecond = 8000;
waveFormat.BlockAlign = 1;
waveFormat.AverageBytesPerSecond = waveFormat.SamplesPerSecond * waveFormat.BlockAlign;
waveFormat.Size = 0;/* (ushort)Marshal.SizeOf(waveFormat);*/
BufferSize = (int)(waveFormat.AverageBytesPerSecond * 2) / 16;
//----------- Буферы --------------------
for (i = 0; i < BuffersCount; i++)
{
waveOutHeader[i].dwFlags = 0x10;//WHDR_INQUEUE;
waveOutHeader[i].dwBufferLength = BufferSize;
waveOutHeader[i].dwBytesRecorded = 0;
waveOutHeader[i].dwUser = IntPtr.Zero;
waveOutHeader[i].dwLoops = 1;
waveOutHeader[i].lpData = Marshal.AllocHGlobal(BufferSize);
}
}
catch (ApplicationException)
{
}
}
//---------------------------------------------------------------
public static void PlayWavFile(string FileName)
{
try
{
if (!File.Exists(FileName)) return;
AudioPlayer = new Audio(FileName);
AudioPlayer.Play();
}
catch (ApplicationException) { }
}
//----------------------------------------------------------------
public static void StopPlayWavFile()
{
try
{
AudioPlayer.Stop();
AudioPlayer.Dispose();
}
catch (ApplicationException) { }
}
#endregion
#region -------------------------- WavOut Function -----------------------------------------------
public static int StartOutAudioDevice(int DeviceID, WaveCallbackProc OutCallBackFun)
{
if (waveOutOpen(ref hWaveOut, DeviceID, ref waveFormat, Marshal.GetFunctionPointerForDelegate(OutCallBackFun), IntPtr.Zero, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
return -1;
return 0;
}
//----------------------------------------------------
public static void PlayBuffer(MemoryStream Stream)
{
while (CurrentBufferNum != BuffersCount)
{
if (waveOutHeader[CurrentBufferNum].dwUser == IntPtr.Zero)
{
byte[] Buff = new byte[BufferSize+1];
Stream.Read(Buff,0,BufferSize);
Marshal.Copy(waveOutHeader[CurrentBufferNum].lpData, Buff, 0, BufferSize);
waveOutPrepareHeader(hWaveOut, ref waveOutHeader[CurrentBufferNum], Marshal.SizeOf(typeof(WAVEHDR)));
waveOutWrite(hWaveOut, ref waveOutHeader[CurrentBufferNum], Marshal.SizeOf(typeof(WAVEHDR)));
waveOutHeader[CurrentBufferNum].dwFlags = 0;
waveOutHeader[CurrentBufferNum].dwBufferLength = BufferSize;
waveOutHeader[CurrentBufferNum].dwBytesRecorded = 0;
waveOutHeader[CurrentBufferNum].dwUser = IntPtr.Zero;
waveOutHeader[CurrentBufferNum].dwLoops = 1;
waveOutHeader[CurrentBufferNum].dwFlags = 0x10;//WHDR_INQUEUE;
//waveOutWrite(hWaveOut, ref waveInHeader, BufferSize);
CurrentBufferNum++;
return;
}
}
}
//-------------------------------------------------------
public static int StopOutAudioDevice()
{
if (hWaveOut == IntPtr.Zero)
return -1;
waveOutClose(hWaveOut);
return 0;
}
#endregion
#region -------------------------- WavIn Function -----------------------------------------------
public static int StartInAudioDevice(int DeviceID, WaveCallbackProc InCallBackFun)
{
if (waveInOpen(ref hWaveIn, DeviceID, ref waveFormat, Marshal.GetFunctionPointerForDelegate(InCallBackFun), IntPtr.Zero, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
return -1;
if (PrepareInBuffer() != 0)
return -2;
if (waveInStart(hWaveIn) != MMSYSERR_NOERROR)
{
Marshal.FreeHGlobal(waveInHeader.lpData);
return -3;
}
return 0;
}
//-------------------------------------------------------
public static int StopInAudioDevice()
{
if (hWaveIn == IntPtr.Zero)
return -1;
waveInStop(hWaveIn);
waveInUnprepareHeader(hWaveIn, ref waveInHeader, Marshal.SizeOf(waveInHeader));
waveInClose(hWaveIn);
hWaveIn = IntPtr.Zero;
return 0;
}
//-------------------------------------------------------
public static int PrepareInBuffer()
{
waveInHeader.lpData = Marshal.AllocHGlobal(BufferSize);
waveInHeader.dwBufferLength = BufferSize;
waveInHeader.dwBytesRecorded = waveInHeader.dwBufferLength;
waveInHeader.dwFlags = 0;
if (waveInPrepareHeader(hWaveIn, ref waveInHeader, Marshal.SizeOf(typeof(WAVEHDR))) != MMSYSERR_NOERROR)
{
Marshal.FreeHGlobal(waveInHeader.lpData);
return -1;
}
if (waveInAddBuffer(hWaveIn, ref waveInHeader, Marshal.SizeOf(typeof(WAVEHDR))) != MMSYSERR_NOERROR)
{
Marshal.FreeHGlobal(waveInHeader.lpData);
return -1;
}
return 0;
}
#endregion
//----------------------------------------------------------------------------
public void Dispose()
{
StopInAudioDevice();
StopOutAudioDevice();
}
//----------------------------------------------------------------------------
}
} |
|
За помощь, огромное спасибо SSTREGG
Теперь основная программа:
Клиент:
Инициализация
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| #region ------------------------ Звук ------------------------------------------
Sound.InitSound();
for (i = 0; i < Sound.InDeviceCount; i++)
if (InAudioDeviceName == Sound.InDeviceName[i])
InAudioDeviceID = (byte)i;
//--------------------
if (Sound.StartInAudioDevice((int)InAudioDeviceID, InCallBackFun) != 0)
InSoundState = Sound.SoundState.None;
else
{
InSoundState = Sound.SoundState.Present;
}
//================================================================================
for (i = 0; i < Sound.OutDeviceCount; i++)
if (OutAudioDeviceName == Sound.OutDeviceName[i])
OutAudioDeviceID = (byte)i;
//--------------------
if (Sound.StartOutAudioDevice((int)OutAudioDeviceID, OutCallBackFun) != 0)
OutSoundState = Sound.SoundState.None;
else
{
OutSoundState = Sound.SoundState.Present;
}
#endregion |
|
КулБаки
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| #region ------ CallBack Audio -------
public static void InCallBackFunction(IntPtr hwi, Sound.WimMessageType uMsg, IntPtr dwInstance, IntPtr dwParam1, IntPtr dwParam2)
{
switch (uMsg)
{
case Sound.WimMessageType.OpenIn:
break;
case Sound.WimMessageType.CloseIn:
break;
case Sound.WimMessageType.DataIn:
Sound.PrepareInBuffer();
switch(InSoundState)
{
case Sound.SoundState.None:
break;
case Sound.SoundState.Ring:
InSoundState = Sound.SoundState.WaitAnswerOnCommand;
break;
case Sound.SoundState.Start:
NetFunClassAudio.SendToNetworkUDP(Sound.waveInHeader.lpData, Sound.waveInHeader.dwBufferLength);
break;
default:
break;
}
break;
}
}
//================================================================================
public static void OutCallBackFunction(IntPtr hwi, Sound.WimMessageType uMsg, IntPtr dwInstance, IntPtr dwParam1, IntPtr dwParam2)
{
switch (uMsg)
{
case Sound.WimMessageType.OpenOut:
break;
case Sound.WimMessageType.CloseOut:
break;
case Sound.WimMessageType.DataOut:
break;
}
}
#endregion |
|
создается доп класс NetFunClassAudio
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
| public class NetProcessAudio
{
public Socket UDPSoundSocketSend;
public IPEndPoint PESoundPointSend;
public UdpClient UPDListerReceive;
public IPEndPoint EPGroupReceive;
public string SendCommand;
public Thread NetThreadReceive;
public bool _NetStartReceive = false;
Sound.SoundState prevState;
//--------------------------
public NetProcessAudio()
{
UDPSoundSocketSend = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
PESoundPointSend = new IPEndPoint(IPAddress.Parse(MainForm.IPServer), Int32.Parse(MainForm.AudioPort) + 1);
UPDListerReceive = new UdpClient(Int32.Parse(MainForm.AudioPort));
EPGroupReceive = new IPEndPoint(IPAddress.Any, Int32.Parse(MainForm.AudioPort));
NetThreadReceive = new Thread(new ThreadStart(ProcessReceive));
NetThreadReceive.IsBackground = true;
NetThreadReceive.Name = "NetThreadReceive";
_NetStartReceive = true;
NetThreadReceive.Start();
}
//--------------------------
~NetProcessAudio()
{
}
//---------------- Send Function ---------------------------------------------
public void SendCommandToNetworkUDP(string Command)
{
byte[] bData = new byte[Command.Length];
int i;
for (i = 0; i < Command.Length; i++)
bData[i] = (byte)Command[i];
UDPSoundSocketSend.SendBufferSize = Command.Length;
UDPSoundSocketSend.ReceiveBufferSize = Command.Length;
UDPSoundSocketSend.SendTo(bData, PESoundPointSend);
MainForm.SaveLogFile("Send " + Command);
SendCommand = Command;
}
//----------------------------------------------------------------------------
public void SendToNetworkUDP(IntPtr DataToSend, int Size)
{
byte[] Data = new byte[Size];
Marshal.Copy(DataToSend, Data, 0, Size);
UDPSoundSocketSend.SendBufferSize = Size;
UDPSoundSocketSend.ReceiveBufferSize = Size;
UDPSoundSocketSend.SendTo(Data, PESoundPointSend);
}
//---------------- Receive Function ------------------------------------------
public void ProcessReceive() // прием данных с микрофона сервера
{
try
{
while (_NetStartReceive)
{
....
switch (MainForm.InSoundState)
{
....
case Sound.SoundState.Start:
byte[] ReceiveBytesData = UPDListerReceive.Receive(ref EPGroupReceive);
using (MemoryStream MStream = new MemoryStream(ReceiveBytesData))
{
if (Sound.CurrentBufferNum == Sound.BuffersCount)
Sound.CurrentBufferNum = 0;
Sound.PlayBuffer(MStream);
}
break;
case Sound.SoundState.Stop:
break;
default:
Thread.Sleep(100);
break;
}
}
}
catch (Exception)
{
return;
}
}
//---------------------------------------
public void NetClose()
{
_NetStartReceive = false;
UPDListerReceive.Close();
}
//--------------------------
}//public class NetProcessAudio
#endregion |
|
Теперь сервер
Инициализация точно такая же как и у клиента, кулбаки такие же, отличие в классе NetProcessAudio
| C# | 1
2
3
4
5
| UDPSoundSocketSend = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
PESoundPointSend = new IPEndPoint(IPAddress.Parse(MainForm.IPClient), Int32.Parse(MainForm.AudioPort));
UPDListerReceive = new UdpClient(Int32.Parse(MainForm.AudioPort) + 1);
EPGroupReceive = new IPEndPoint(IPAddress.Any, Int32.Parse(MainForm.AudioPort) + 1); |
|
Вроде должно работать, ан нет... один хриплый повторяющийся звук
Пробовал соединить и клиент и сервер в одной программе, такое же.
Не пойму, в чем дело или с микрофона звук крива снимается (но что то не вериться), или на динамик
криво кидаю (что быстрей всего).
Тюкните мордой пожалуйста, где я накасячил
Заранее благодарен.
ЗЫ: Сильно не пинайте
1
|