📄 threads.cpp
字号:
/*
Talker - A small program which utilizes the Layer-3 codec (ACM) in windows for voice-over-IP
Copyright (C) 1999 Dino Klein
This program is free software; you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with this
program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
MA 02139, USA.
email: dinoklein@hotmail.com
*/
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>
#include <stdio.h>
#include "defines.h"
#include <dsound.h>
extern bool stereo;
extern int queue_size;
extern sound_sec sqq[MAX_QUEUE];
extern int index_take, index_put;
extern bool dbl;
extern bool blocks_got[16];
extern unsigned char total_blocks;
extern char output_buffer[4096];
extern CRITICAL_SECTION cs;
extern SOCKET ssin, sout;
extern unsigned short next_send_id, next_receive_id;
extern HACMSTREAM has, hasd;
extern HANDLE hPlay, hRec[4], hTerminate, hData;
extern ACMSTREAMHEADER ahc, ahd;
extern char tempbuf [4096];
extern HWND talker_dlg;
extern char dst_addr_txt [16];
extern char listen_mode;
extern unsigned long dst_addr;
extern int input_buffer_size, lock_size, segments, output_buf_size;
extern WAVEFORMATEX wfx;
DWORD ticks;
bool zero_output_buffer (void);
extern LPDIRECTSOUNDCAPTUREBUFFER lpdscb;
extern LPDIRECTSOUNDBUFFER lpdsb;
#define MAX_SOUND_DATA 541 // 540
DWORD WINAPI sender (LPVOID lpv)
{
DWORD r;
HANDLE things[11];
SOUND_PACKET out_sp;
DWORD cb1, cb2;
LPVOID pv1, pv2;
int lock_from, to_lock;
lock_from = 0;
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
things[0] = hTerminate;
for (int i=0; i<11; i++) things[i+1] = hRec[i];
for (;;)
{
r = WaitForMultipleObjects (11, things, 0, INFINITE);
if (r == WAIT_OBJECT_0) break;
r -= WAIT_OBJECT_0;
lock_from = (r-1) * lock_size;
if (r==segments) to_lock = input_buffer_size-lock_from;
else to_lock = lock_size;
if (lpdscb->Lock(lock_from, lock_size, &pv1, &cb1, &pv2, &cb2, 0)!=DS_OK) continue;
ahc.cbSrcLength = cb1;
memcpy(ahc.pbSrc, pv1, cb1);
lpdscb->Unlock(pv1, cb1, pv2, cb2);
DWORD d = GetTickCount();
r = acmStreamConvert (has, &ahc, ACM_STREAMCONVERTF_START|ACM_STREAMCONVERTF_BLOCKALIGN);
d = GetTickCount() - d;
PostMessage(talker_dlg, ST_SIZE, (WPARAM) d, 0);
if (!r)
{
int index = 0, tocopy, t;
out_sp.sph.uid = 0x5A5A;
out_sp.sph.ordinal_id = next_send_id;
out_sp.sph.extra = (ahc.cbDstLengthUsed/MAX_SOUND_DATA)<<4;
for (t=0;;t++)
{
tocopy = ahc.cbDstLengthUsed-index;
if (tocopy>MAX_SOUND_DATA) tocopy = MAX_SOUND_DATA;
out_sp.sph.extra = (out_sp.sph.extra&0xF0) | t;
memcpy(out_sp.data, &ahc.pbDst[index], tocopy);
out_sp.sph.length = tocopy;
send (sout, (char *) &out_sp, sizeof (SOUND_PACKET_HEADER) + out_sp.sph.length, 0);
if (dbl) send(sout, (char *) &out_sp, sizeof (SOUND_PACKET_HEADER) + out_sp.sph.length, 0);
index += tocopy;
if (t==(ahc.cbDstLengthUsed/MAX_SOUND_DATA)) break;
}
PostMessage(talker_dlg, ST_ERR, (WPARAM) ahc.cbDstLengthUsed, t+1);
next_send_id++;
}
}
ExitThread (0);
return (0);
}
/*
need to keep track of the pointer and zero out the
buffer only once when needed, and not waste cycles
as it is done now
*/
DWORD WINAPI actual_player (LPVOID lpv)
{
DWORD write_offset;
bool buffer_blank;
HANDLE *stuff; //[0] = terminate event; [1] = data; [2] = pipe
DWORD cb1, cb2;
LPVOID pv1, pv2;
HRESULT hr;
DWORD pplay, pwrite, bytes_in_pipe, bytes_wrote_to_buf, free_for_lock;
DWORD bytes_read;
char dump[8192];
//FILE *fp = fopen("c:\\check.dat", "rb");
stuff = (HANDLE*)lpv;
buffer_blank = true;
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
for (;;)
{
PeekNamedPipe(stuff[2], 0, 0, 0, &bytes_in_pipe, 0);
if (bytes_in_pipe) bytes_in_pipe -= bytes_in_pipe%wfx.nBlockAlign;
hr = lpdsb->GetCurrentPosition(&pplay, &pwrite);
if (hr==DS_OK)
{
if (buffer_blank)
{
lpdsb->SetCurrentPosition(0);
zero_output_buffer();
write_offset = 0;
free_for_lock = output_buf_size-output_buf_size%wfx.nBlockAlign;
}
else
{
// check if write_offset is in a valid place, in case of computer slowness
if (pwrite>pplay)
if ((write_offset>=pplay)&&(write_offset<pwrite)) write_offset = pwrite;
else;
else if (write_offset<pwrite || write_offset>=pplay) write_offset = pwrite;
// in case windows does not copies in n*BlockAlign steps, which
// I kinda tested and it seems like it doesn't always do that, so, what the heck
if (write_offset && (write_offset%wfx.nBlockAlign))
{
write_offset = write_offset+(wfx.nBlockAlign-write_offset%wfx.nBlockAlign);
if (write_offset>=output_buf_size) write_offset -= output_buf_size;
}
// calc how many bytes we can write into the buffer
if (write_offset>pplay) free_for_lock = output_buf_size-write_offset+pplay;
else free_for_lock = pplay-write_offset;
free_for_lock -= free_for_lock%wfx.nBlockAlign;
}
hr = lpdsb->Lock(write_offset, free_for_lock, &pv1, &cb1, &pv2, &cb2, 0);
if (hr==DS_OK)
{
bytes_wrote_to_buf = 0;
if (bytes_in_pipe)
{
ReadFile(stuff[2], pv1, (bytes_in_pipe>cb1)?cb1:bytes_in_pipe, &bytes_read, 0);
//fwrite(pv1, bytes_read, 1, fp);
bytes_in_pipe -= bytes_read;
bytes_wrote_to_buf += bytes_read;
if (bytes_in_pipe && pv2)
{
ReadFile(stuff[2], pv2, (bytes_in_pipe>cb2)?cb2:bytes_in_pipe, &bytes_read, 0);
//fwrite(pv2, bytes_read, 1, fp);
bytes_wrote_to_buf += bytes_read;
}
}
if (bytes_wrote_to_buf<cb1)
{
memset((char*)pv1+bytes_wrote_to_buf, 0, cb1-bytes_wrote_to_buf);
if (pv2) memset(pv2, 0, cb2);
}
else if (pv2 && (bytes_wrote_to_buf-cb1)<cb2) memset((char*)pv2+bytes_wrote_to_buf-cb1, 0, cb2-(bytes_wrote_to_buf-cb1));
lpdsb->Unlock(pv1, cb1, pv2, cb2);
write_offset += bytes_wrote_to_buf;
if (write_offset>=output_buf_size) write_offset -= output_buf_size;
if (buffer_blank)
{
buffer_blank = false;
lpdsb->Play(0, 0, DSBPLAY_LOOPING);
}
}
}
if (hr==DSERR_BUFFERLOST)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -