摘要:在pc上使用adb命令:adb forward tcp:4626 tcp:4883,在PC上建立4626端口通信数据将被重定向到手机端server的4883端口;然后初始化socket,连接到手机4626端口,进行socket通信。PC端代码如下:

小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。

在pc上使用adb命令:adb forward tcp:4626 tcp:4883,在PC上建立4626端口通信数据将被重定向到手机端server的4883端口;然后初始化socket,连接到手机4626端口,进行socket通信。PC端代码如下:

?

[html]?
DWORD WINAPI usbThreadFunc(LPVOID threadNum)?
{?
??? int length;??
??? CString temp;?
??? if(!initAdb())//adb init?
??? {?
??????? MessageBox(0, L"初始化手机出错!", L"提示", MB_OK);?
??????? return 0;?
??? }?
??? if(!InItClientSock())//socket init?
??? {?
??????? MessageBox(0, L"初始化IP地址出错!", L"提示", MB_OK);?
??????? return 0;?
??? }?
??? if(!USBConnectSock((HWND)threadNum))//connect socket?
??? {?
??????? MessageBox(0, L"连接IP地址出错!", L"提示", MB_OK);?
??????? return 0;?
??? }?
??? //等待连接的时候,连接可能被取消。?
??? if(clientThreadRun)?
??? {?
??? }?
??? else?
??? {?
??????? MessageBox(0, L"用户取消!", L"提示", MB_OK);?
??????? return 0;?
??? }?
??? SetDlgItemText( (HWND)threadNum, IDC_SOUNDFILE, TEXT("&USB Disconnect") );?
??? EnableWindow( GetDlgItem( (HWND)threadNum, IDC_RECORD ), TRUE );?
??? EnableWindow( GetDlgItem( (HWND)threadNum, IDC_BUTTON_WIFI ), FALSE );???
??? while(clientThreadRun)?
??? {?
??????? if( (length = recv(clientSock,(char*)recv_message_client,sizeof(recv_message_client),0))>0)?
??????? {?
??????????? memset(recv_message_client, 0, sizeof(recv_message_client));?
??????????? LogPrintf(recv_message_client);?
??????? }????????
??? }?
??? return 0;?
}?

DWORD WINAPI usbThreadFunc(LPVOID threadNum)
{
?int length;?
?CString temp;
?if(!initAdb())//adb init
?{
??MessageBox(0, L"初始化手机出错!", L"提示", MB_OK);
??return 0;
?}
?if(!InItClientSock())//socket init
?{
??MessageBox(0, L"初始化IP地址出错!", L"提示", MB_OK);
??return 0;
?}
?if(!USBConnectSock((HWND)threadNum))//connect socket
?{
??MessageBox(0, L"连接IP地址出错!", L"提示", MB_OK);
??return 0;
?}
?//等待连接的时候,连接可能被取消。
?if(clientThreadRun)
?{
?}
?else
?{
??MessageBox(0, L"用户取消!", L"提示", MB_OK);
??return 0;
?}
?SetDlgItemText( (HWND)threadNum, IDC_SOUNDFILE, TEXT("&USB Disconnect") );
?EnableWindow( GetDlgItem( (HWND)threadNum, IDC_RECORD ), TRUE );
?EnableWindow( GetDlgItem( (HWND)threadNum, IDC_BUTTON_WIFI ), FALSE );?
?while(clientThreadRun)
?{
??if( (length = recv(clientSock,(char*)recv_message_client,sizeof(recv_message_client),0))>0)
??{
???memset(recv_message_client, 0, sizeof(recv_message_client));
???LogPrintf(recv_message_client);
??}??
?}
?return 0;
}

这里说道最重要的是捕获声音,下面的代码启动了一个线程来处理捕获到的声音:

[html]?
DWORD WINAPI captureThreadFunc(LPVOID hDlg)?
{?
??? DWORD dwResult;?
??? while(g_bRecording)??
??? {??
??????? dwResult = MsgWaitForMultipleObjects( 1, &g_hNotificationEvent, FALSE, INFINITE, QS_ALLEVENTS );?
??????? switch( dwResult )?
??????? {?
??????? case STATUS_WAIT_0://case WAIT_OBJECT_0 + 0:?
?
??????????? RecordCapturedData();?
??????????? break;?
??????? }?
??? }?
??? return 0;?
}?

DWORD WINAPI captureThreadFunc(LPVOID hDlg)
{
?DWORD dwResult;
?while(g_bRecording)
?{
??dwResult = MsgWaitForMultipleObjects( 1, &g_hNotificationEvent, FALSE, INFINITE, QS_ALLEVENTS );
??switch( dwResult )
??{
??case STATUS_WAIT_0://case WAIT_OBJECT_0 + 0:

???RecordCapturedData();
???break;
??}
?}
?return 0;
}

在创建捕获声音的设备的时候,会创建一个事件,这个事件就是捕获到一定长度的声音之后(比如2K大小的声音),会发出一个通知,告诉你去处理。上面的线程,就是一直待等待这个事件,然后再去处理捕获到的声音,把声音发送给socket,交给手机处理,代码:

[html]?
HRESULT RecordCapturedData()??
{?
??? HRESULT hr;?
??? VOID*?? pbCaptureData??? = NULL;?
??? DWORD?? dwCaptureLength;?
??? VOID*?? pbCaptureData2?? = NULL;?
??? DWORD?? dwCaptureLength2;?
??? DWORD?? dwReadPos;?
??? DWORD?? dwCapturePos;?
??? LONG lLockSize;?
?
??? if( NULL == g_pDSBCapture )?
??????? return S_FALSE;?
?
??? if( FAILED( hr = g_pDSBCapture->GetCurrentPosition( &dwCapturePos, &dwReadPos ) ) )?
??????? return DXTRACE_ERR_MSGBOX( TEXT("GetCurrentPosition"), hr );?
?
??? lLockSize = dwReadPos - g_dwNextCaptureOffset;?
??? if( lLockSize < 0 )?
??????? lLockSize += g_dwCaptureBufferSize;?
?
??? // Block align lock size so that we are always write on a boundary?
??? lLockSize -= (lLockSize % g_dwNotifySize);?
?
??? if( lLockSize == 0 )?
??????? return S_FALSE;?
?
??? // Lock the capture buffer down?
??? if( FAILED( hr = g_pDSBCapture->Lock( g_dwNextCaptureOffset, lLockSize,??
????????????????????????????????????????? &pbCaptureData, &dwCaptureLength,??
????????????????????????????????????????? &pbCaptureData2, &dwCaptureLength2, 0L ) ) )?
??????? return DXTRACE_ERR_MSGBOX( TEXT("Lock"), hr );?
?
?????
??? // Write the data to socket发送给手机?
??? socketSend(pbCaptureData,dwCaptureLength);?
??? // Move the capture offset along?
??? g_dwNextCaptureOffset += dwCaptureLength;??
??? g_dwNextCaptureOffset %= g_dwCaptureBufferSize; // Circular buffer?
?
??? if( pbCaptureData2 != NULL )?
??? {?
??????? // Write the data to socket发送给手机?
??????? socketSend(pbCaptureData2,dwCaptureLength2);?
?
??????? // Move the capture offset along?
??????? g_dwNextCaptureOffset += dwCaptureLength2;??
??????? g_dwNextCaptureOffset %= g_dwCaptureBufferSize; // Circular buffer?
??? }?
?
??? // Unlock the capture buffer?
??? g_pDSBCapture->Unlock( pbCaptureData,? dwCaptureLength,??
?????????????????????????? pbCaptureData2, dwCaptureLength2 );?
??? return S_OK;?
}?

HRESULT RecordCapturedData()
{
??? HRESULT hr;
??? VOID*?? pbCaptureData??? = NULL;
??? DWORD?? dwCaptureLength;
??? VOID*?? pbCaptureData2?? = NULL;
??? DWORD?? dwCaptureLength2;
??? DWORD?? dwReadPos;
??? DWORD?? dwCapturePos;
??? LONG lLockSize;

??? if( NULL == g_pDSBCapture )
??????? return S_FALSE;

??? if( FAILED( hr = g_pDSBCapture->GetCurrentPosition( &dwCapturePos, &dwReadPos ) ) )
??????? return DXTRACE_ERR_MSGBOX( TEXT("GetCurrentPosition"), hr );

??? lLockSize = dwReadPos - g_dwNextCaptureOffset;
??? if( lLockSize < 0 )
??????? lLockSize += g_dwCaptureBufferSize;

??? // Block align lock size so that we are always write on a boundary
??? lLockSize -= (lLockSize % g_dwNotifySize);

??? if( lLockSize == 0 )
??????? return S_FALSE;

??? // Lock the capture buffer down
??? if( FAILED( hr = g_pDSBCapture->Lock( g_dwNextCaptureOffset, lLockSize,
????????????????????????????????????????? &pbCaptureData, &dwCaptureLength,
????????????????????????????????????????? &pbCaptureData2, &dwCaptureLength2, 0L ) ) )
??????? return DXTRACE_ERR_MSGBOX( TEXT("Lock"), hr );

?
??? // Write the data to socket发送给手机
?socketSend(pbCaptureData,dwCaptureLength);
??? // Move the capture offset along
??? g_dwNextCaptureOffset += dwCaptureLength;
??? g_dwNextCaptureOffset %= g_dwCaptureBufferSize; // Circular buffer

??? if( pbCaptureData2 != NULL )
??? {
??????? // Write the data to socket发送给手机
???socketSend(pbCaptureData2,dwCaptureLength2);

??????? // Move the capture offset along
??????? g_dwNextCaptureOffset += dwCaptureLength2;
??????? g_dwNextCaptureOffset %= g_dwCaptureBufferSize; // Circular buffer
??? }

??? // Unlock the capture buffer
??? g_pDSBCapture->Unlock( pbCaptureData,? dwCaptureLength,
?????????????????????????? pbCaptureData2, dwCaptureLength2 );
??? return S_OK;
}

通过socket发送数据的代码很简单,没有任何处理捕获到的声音数据,就发送给手机了

[html]
VOID socketSend(VOID* send_message, int length)?
{?
??? if(clientSockConnect==0)?
??? {????????
??????? int send_len = length;?
??????? char * buf = (char*)send_message;?
?
??????? while(send_len>0)?
??????? {????????
??????????? int rc = send(clientSock,buf,send_len, 0);//MSG_OOB?
??????????? if (rc < 1)//if (rc == SOCKET_ERROR || rc == 0)?
??????????? {?
??????????????? break;?
??????????? }????
??????????? send_len -= rc;?
??????????? buf += rc;?
??????? }?
??????? buf = NULL;?
??? }?
}?

VOID socketSend(VOID* send_message, int length)
{
?if(clientSockConnect==0)
?{??
??int send_len = length;
??char * buf = (char*)send_message;

??while(send_len>0)
??{??
???int rc = send(clientSock,buf,send_len, 0);//MSG_OOB
???if (rc < 1)//if (rc == SOCKET_ERROR || rc == 0)
???{
????break;
???}?
???send_len -= rc;
???buf += rc;
??}
??buf = NULL;
?}
}
手机端的代码如下,注意手机上audioTrack的设置:44100,AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT。在启动电脑捕获声音的时候也要同样的设置,否则播放的声音是杂音:

[html]?
public class TcpConnect extends Thread {?
??? private ServerSocket mServerSocket;?
??? private Socket mClient;?
??? private Handler mHandler;?
??? private boolean running = false;?
??? private boolean palying = false;?
?
??? private int audioPlayBufSize;?
??? private AudioTrack audioTrack;?
??? private static final int frequency = 44100;?
??? private static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;?
??? private static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;?
?
??? private ArrayList inBuf = new ArrayList();?
?
??? public TcpConnect(Handler handler) {?
??????? mHandler = handler;?
?
??????? audioPlayBufSize = AudioTrack.getMinBufferSize(frequency,?
??????????????? channelConfiguration, audioEncoding);?
??????? audioTrack = new AudioTrack(?
??????????????? AudioManager.STREAM_MUSIC,// .STREAM_RING,//.STREAM_MUSIC,?
??????????????? frequency, channelConfiguration, audioEncoding,?
??????????????? audioPlayBufSize, AudioTrack.MODE_STREAM);?
??????? audioTrack.setStereoVolume(1.0f, 1.0f);?
??????? Log.d("playPCAudio", "audioPlayBufSize: " + audioPlayBufSize);?
?
??????? palying = false;?
??????? inBuf.clear();?
??? }?
?
??? public void run() {?
??????? try {?
??????????? mServerSocket = new ServerSocket(4883);?
?
??????????? System.out.println("TcpConnect" + "开始监听");?
??????????? mClient = mServerSocket.accept();?
??????????? System.out.println("TcpConnect" + "检测到有连接");?
??????????? InputStream is = mClient.getInputStream();?
?
??????????? running = true;?
??????????? int readLen = 0;?
??????????? byte[] readBuf = new byte[audioPlayBufSize];?
?
??????????? System.out.println("TcpConnect" + "接收");?
??????????? playThread palyt = new playThread();?
??????????? palyt.setPriority(Thread.MAX_PRIORITY);?
??????????? palyt.start();?
?
??????????? while (running) {?
??????????????? if ((readLen = is.read(readBuf, 0, audioPlayBufSize)) > 0) {?
??????????????????? byte[] tmpBuf = new byte[readLen];?
??????????????????? System.arraycopy(readBuf, 0, tmpBuf, 0, readLen);?
??????????????????? synchronized (inBuf) {?
??????????????????????? inBuf.add(tmpBuf);?
??????????????????? }?
??????????????? }?
??????????? }?
??????? } catch (Exception e) {?
??????????? System.out.println("TcpConnect TCP error:" + e.getMessage());?
??????? }?
??????? System.out.println("TcpConnect over");?
??? }?
?
??? class playThread extends Thread {?
?
??????? public playThread() {?
??????? }?
??????? public void run() {?
??????????? audioTrack.play();?
??????????? palying = true;?
?
??????????? while (running) {?
??????????????? ArrayList buf = new ArrayList();?
??????????????? buf.clear();?
??????????????? synchronized (inBuf) {?
??????????????????? if (inBuf.size() == 0)?
??????????????????????? continue;?
??????????????????? buf = (ArrayList) inBuf.clone();?
??????????????????? inBuf.clear();?
??????????????? }?
??????????????? for (int i = 0; i < buf.size(); i++) {?
??????????????????? byte[] tmpBuf = buf.get(i);?
??????????????????? audioTrack.write(tmpBuf, 0, tmpBuf.length);?
??????????????? }?
??????????? }?
??????????? if (palying) {?
??????????????? audioTrack.stop();?
??????????????? audioTrack.release();?
??????????????? palying = false;?
??????????? }?
??????? }?
??? }?
}?

在pc上使用adb命令:adb forward tcp:4626 tcp:4883,在PC上建立4626端口通信数据将被重定向到手机端server的4883端口;然后初始化socket,连接到手机4626端口,进行socket通信。PC端代码如下:

?

[html]?
DWORD WINAPI usbThreadFunc(LPVOID threadNum)?
{?
??? int length;??
??? CString temp;?
??? if(!initAdb())//adb init?
??? {?
??????? MessageBox(0, L"初始化手机出错!", L"提示", MB_OK);?
??????? return 0;?
??? }?
??? if(!InItClientSock())//socket init?
??? {?
??????? MessageBox(0, L"初始化IP地址出错!", L"提示", MB_OK);?
??????? return 0;?
??? }?
??? if(!USBConnectSock((HWND)threadNum))//connect socket?
??? {?
??????? MessageBox(0, L"连接IP地址出错!", L"提示", MB_OK);?
??????? return 0;?
??? }?
??? //等待连接的时候,连接可能被取消。?
??? if(clientThreadRun)?
??? {?
??? }?
??? else?
??? {?
??????? MessageBox(0, L"用户取消!", L"提示", MB_OK);?
??????? return 0;?
??? }?
??? SetDlgItemText( (HWND)threadNum, IDC_SOUNDFILE, TEXT("&USB Disconnect") );?
??? EnableWindow( GetDlgItem( (HWND)threadNum, IDC_RECORD ), TRUE );?
??? EnableWindow( GetDlgItem( (HWND)threadNum, IDC_BUTTON_WIFI ), FALSE );???
??? while(clientThreadRun)?
??? {?
??????? if( (length = recv(clientSock,(char*)recv_message_client,sizeof(recv_message_client),0))>0)?
??????? {?
??????????? memset(recv_message_client, 0, sizeof(recv_message_client));?
??????????? LogPrintf(recv_message_client);?
??????? }????????
??? }?
??? return 0;?
}?

DWORD WINAPI usbThreadFunc(LPVOID threadNum)
{
?int length;?
?CString temp;
?if(!initAdb())//adb init
?{
??MessageBox(0, L"初始化手机出错!", L"提示", MB_OK);
??return 0;
?}
?if(!InItClientSock())//socket init
?{
??MessageBox(0, L"初始化IP地址出错!", L"提示", MB_OK);
??return 0;
?}
?if(!USBConnectSock((HWND)threadNum))//connect socket
?{
??MessageBox(0, L"连接IP地址出错!", L"提示", MB_OK);
??return 0;
?}
?//等待连接的时候,连接可能被取消。
?if(clientThreadRun)
?{
?}
?else
?{
??MessageBox(0, L"用户取消!", L"提示", MB_OK);
??return 0;
?}
?SetDlgItemText( (HWND)threadNum, IDC_SOUNDFILE, TEXT("&USB Disconnect") );
?EnableWindow( GetDlgItem( (HWND)threadNum, IDC_RECORD ), TRUE );
?EnableWindow( GetDlgItem( (HWND)threadNum, IDC_BUTTON_WIFI ), FALSE );?
?while(clientThreadRun)
?{
??if( (length = recv(clientSock,(char*)recv_message_client,sizeof(recv_message_client),0))>0)
??{
???memset(recv_message_client, 0, sizeof(recv_message_client));
???LogPrintf(recv_message_client);
??}??
?}
?return 0;
}

这里说道最重要的是捕获声音,下面的代码启动了一个线程来处理捕获到的声音:

[html]?
DWORD WINAPI captureThreadFunc(LPVOID hDlg)?
{?
??? DWORD dwResult;?
??? while(g_bRecording)??
??? {??
??????? dwResult = MsgWaitForMultipleObjects( 1, &g_hNotificationEvent, FALSE, INFINITE, QS_ALLEVENTS );?
??????? switch( dwResult )?
??????? {?
??????? case STATUS_WAIT_0://case WAIT_OBJECT_0 + 0:?
?
??????????? RecordCapturedData();?
??????????? break;?
??????? }?
??? }?
??? return 0;?
}?

DWORD WINAPI captureThreadFunc(LPVOID hDlg)
{
?DWORD dwResult;
?while(g_bRecording)
?{
??dwResult = MsgWaitForMultipleObjects( 1, &g_hNotificationEvent, FALSE, INFINITE, QS_ALLEVENTS );
??switch( dwResult )
??{
??case STATUS_WAIT_0://case WAIT_OBJECT_0 + 0:

???RecordCapturedData();
???break;
??}
?}
?return 0;
}

在创建捕获声音的设备的时候,会创建一个事件,这个事件就是捕获到一定长度的声音之后(比如2K大小的声音),会发出一个通知,告诉你去处理。上面的线程,就是一直待等待这个事件,然后再去处理捕获到的声音,把声音发送给socket,交给手机处理,代码:

[html]?
HRESULT RecordCapturedData()??
{?
??? HRESULT hr;?
??? VOID*?? pbCaptureData??? = NULL;?
??? DWORD?? dwCaptureLength;?
??? VOID*?? pbCaptureData2?? = NULL;?
??? DWORD?? dwCaptureLength2;?
??? DWORD?? dwReadPos;?
??? DWORD?? dwCapturePos;?
??? LONG lLockSize;?
?
??? if( NULL == g_pDSBCapture )?
??????? return S_FALSE;?
?
??? if( FAILED( hr = g_pDSBCapture->GetCurrentPosition( &dwCapturePos, &dwReadPos ) ) )?
??????? return DXTRACE_ERR_MSGBOX( TEXT("GetCurrentPosition"), hr );?
?
??? lLockSize = dwReadPos - g_dwNextCaptureOffset;?
??? if( lLockSize < 0 )?
??????? lLockSize += g_dwCaptureBufferSize;?
?
??? // Block align lock size so that we are always write on a boundary?
??? lLockSize -= (lLockSize % g_dwNotifySize);?
?
??? if( lLockSize == 0 )?
??????? return S_FALSE;?
?
??? // Lock the capture buffer down?
??? if( FAILED( hr = g_pDSBCapture->Lock( g_dwNextCaptureOffset, lLockSize,??
????????????????????????????????????????? &pbCaptureData, &dwCaptureLength,??
????????????????????????????????????????? &pbCaptureData2, &dwCaptureLength2, 0L ) ) )?
??????? return DXTRACE_ERR_MSGBOX( TEXT("Lock"), hr );?
?
?????
??? // Write the data to socket发送给手机?
??? socketSend(pbCaptureData,dwCaptureLength);?
??? // Move the capture offset along?
??? g_dwNextCaptureOffset += dwCaptureLength;??
??? g_dwNextCaptureOffset %= g_dwCaptureBufferSize; // Circular buffer?
?
??? if( pbCaptureData2 != NULL )?
??? {?
??????? // Write the data to socket发送给手机?
??????? socketSend(pbCaptureData2,dwCaptureLength2);?
?
??????? // Move the capture offset along?
??????? g_dwNextCaptureOffset += dwCaptureLength2;??
??????? g_dwNextCaptureOffset %= g_dwCaptureBufferSize; // Circular buffer?
??? }?
?
??? // Unlock the capture buffer?
??? g_pDSBCapture->Unlock( pbCaptureData,? dwCaptureLength,??
?????????????????????????? pbCaptureData2, dwCaptureLength2 );?
??? return S_OK;?
}?

HRESULT RecordCapturedData()
{
??? HRESULT hr;
??? VOID*?? pbCaptureData??? = NULL;
??? DWORD?? dwCaptureLength;
??? VOID*?? pbCaptureData2?? = NULL;
??? DWORD?? dwCaptureLength2;
??? DWORD?? dwReadPos;
??? DWORD?? dwCapturePos;
??? LONG lLockSize;

??? if( NULL == g_pDSBCapture )
??????? return S_FALSE;

??? if( FAILED( hr = g_pDSBCapture->GetCurrentPosition( &dwCapturePos, &dwReadPos ) ) )
??????? return DXTRACE_ERR_MSGBOX( TEXT("GetCurrentPosition"), hr );

??? lLockSize = dwReadPos - g_dwNextCaptureOffset;
??? if( lLockSize < 0 )
??????? lLockSize += g_dwCaptureBufferSize;

??? // Block align lock size so that we are always write on a boundary
??? lLockSize -= (lLockSize % g_dwNotifySize);

??? if( lLockSize == 0 )
??????? return S_FALSE;

??? // Lock the capture buffer down
??? if( FAILED( hr = g_pDSBCapture->Lock( g_dwNextCaptureOffset, lLockSize,
????????????????????????????????????????? &pbCaptureData, &dwCaptureLength,
????????????????????????????????????????? &pbCaptureData2, &dwCaptureLength2, 0L ) ) )
??????? return DXTRACE_ERR_MSGBOX( TEXT("Lock"), hr );

?
??? // Write the data to socket发送给手机
?socketSend(pbCaptureData,dwCaptureLength);
??? // Move the capture offset along
??? g_dwNextCaptureOffset += dwCaptureLength;
??? g_dwNextCaptureOffset %= g_dwCaptureBufferSize; // Circular buffer

??? if( pbCaptureData2 != NULL )
??? {
??????? // Write the data to socket发送给手机
???socketSend(pbCaptureData2,dwCaptureLength2);

??????? // Move the capture offset along
??????? g_dwNextCaptureOffset += dwCaptureLength2;
??????? g_dwNextCaptureOffset %= g_dwCaptureBufferSize; // Circular buffer
??? }

??? // Unlock the capture buffer
??? g_pDSBCapture->Unlock( pbCaptureData,? dwCaptureLength,
?????????????????????????? pbCaptureData2, dwCaptureLength2 );
??? return S_OK;
}

通过socket发送数据的代码很简单,没有任何处理捕获到的声音数据,就发送给手机了

[html]
VOID socketSend(VOID* send_message, int length)?
{?
??? if(clientSockConnect==0)?
??? {????????
??????? int send_len = length;?
??????? char * buf = (char*)send_message;?
?
??????? while(send_len>0)?
??????? {????????
??????????? int rc = send(clientSock,buf,send_len, 0);//MSG_OOB?
??????????? if (rc < 1)//if (rc == SOCKET_ERROR || rc == 0)?
??????????? {?
??????????????? break;?
??????????? }????
??????????? send_len -= rc;?
??????????? buf += rc;?
??????? }?
??????? buf = NULL;?
??? }?
}?

VOID socketSend(VOID* send_message, int length)
{
?if(clientSockConnect==0)
?{??
??int send_len = length;
??char * buf = (char*)send_message;

??while(send_len>0)
??{??
???int rc = send(clientSock,buf,send_len, 0);//MSG_OOB
???if (rc < 1)//if (rc == SOCKET_ERROR || rc == 0)
???{
????break;
???}?
???send_len -= rc;
???buf += rc;
??}
??buf = NULL;
?}
}
手机端的代码如下,注意手机上audioTrack的设置:44100,AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT。在启动电脑捕获声音的时候也要同样的设置,否则播放的声音是杂音:

[html]?
public class TcpConnect extends Thread {?
??? private ServerSocket mServerSocket;?
??? private Socket mClient;?
??? private Handler mHandler;?
??? private boolean running = false;?
??? private boolean palying = false;?
?
??? private int audioPlayBufSize;?
??? private AudioTrack audioTrack;?
??? private static final int frequency = 44100;?
??? private static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;?
??? private static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;?
?
??? private ArrayList inBuf = new ArrayList();?
?
??? public TcpConnect(Handler handler) {?
??????? mHandler = handler;?
?
??????? audioPlayBufSize = AudioTrack.getMinBufferSize(frequency,?
??????????????? channelConfiguration, audioEncoding);?
??????? audioTrack = new AudioTrack(?
??????????????? AudioManager.STREAM_MUSIC,// .STREAM_RING,//.STREAM_MUSIC,?
??????????????? frequency, channelConfiguration, audioEncoding,?
??????????????? audioPlayBufSize, AudioTrack.MODE_STREAM);?
??????? audioTrack.setStereoVolume(1.0f, 1.0f);?
??????? Log.d("playPCAudio", "audioPlayBufSize: " + audioPlayBufSize);?
?
??????? palying = false;?
??????? inBuf.clear();?
??? }?
?
??? public void run() {?
??????? try {?
??????????? mServerSocket = new ServerSocket(4883);?
?
??????????? System.out.println("TcpConnect" + "开始监听");?
??????????? mClient = mServerSocket.accept();?
??????????? System.out.println("TcpConnect" + "检测到有连接");?
??????????? InputStream is = mClient.getInputStream();?
?
??????????? running = true;?
??????????? int readLen = 0;?
??????????? byte[] readBuf = new byte[audioPlayBufSize];?
?
??????????? System.out.println("TcpConnect" + "接收");?
??????????? playThread palyt = new playThread();?
??????????? palyt.setPriority(Thread.MAX_PRIORITY);?
??????????? palyt.start();?
?
??????????? while (running) {?
??????????????? if ((readLen = is.read(readBuf, 0, audioPlayBufSize)) > 0) {?
??????????????????? byte[] tmpBuf = new byte[readLen];?
??????????????????? System.arraycopy(readBuf, 0, tmpBuf, 0, readLen);?
??????????????????? synchronized (inBuf) {?
??????????????????????? inBuf.add(tmpBuf);?
??????????????????? }?
??????????????? }?
??????????? }?
??????? } catch (Exception e) {?
??????????? System.out.println("TcpConnect TCP error:" + e.getMessage());?
??????? }?
??????? System.out.println("TcpConnect over");?
??? }?
?
??? class playThread extends Thread {?
?
??????? public playThread() {?
??????? }?
??????? public void run() {?
??????????? audioTrack.play();?
??????????? palying = true;?
?
??????????? while (running) {?
??????????????? ArrayList buf = new ArrayList();?
??????????????? buf.clear();?
??????????????? synchronized (inBuf) {?
??????????????????? if (inBuf.size() == 0)?
??????????????????????? continue;?
??????????????????? buf = (ArrayList) inBuf.clone();?
??????????????????? inBuf.clear();?
??????????????? }?
??????????????? for (int i = 0; i < buf.size(); i++) {?
??????????????????? byte[] tmpBuf = buf.get(i);?
??????????????????? audioTrack.write(tmpBuf, 0, tmpBuf.length);?
??????????????? }?
??????????? }?
??????????? if (palying) {?
??????????????? audioTrack.stop();?
??????????????? audioTrack.release();?
??????????????? palying = false;?
??????????? }?
??????? }?
??? }?
}?

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦!?html5教程,巧夺天工,精雕玉琢。小宝典献丑了!

本文固定链接: http://www.js-code.com/html5%e6%95%99%e7%a8%8b/html5%e6%95%99%e7%a8%8b_3006.html