📄 main.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 "resource.h"
// external functions
char init_sockets (void);
void close_sockets (void);
char init_sound (void);
void close_sound (void);
DWORD WINAPI sender (LPVOID);
DWORD WINAPI receiver (LPVOID);
DWORD WINAPI player (LPVOID);
BOOL CALLBACK addr_dialog (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK talk_dialog (HWND, UINT, WPARAM, LPARAM);
int queue_size;
sound_sec sqq[MAX_QUEUE];
int index_put, index_take;
bool dbl;
HANDLE heap; // maybe will use this for allocating memory dynamically for the ACM
int band; // stupid name
bool stereo, use_primary;
bool blocks_got[16];
unsigned char total_blocks;
char acmbuf[44100];
char output_buffer[4096];
char decomp_buf[44100];
char comped_buf[4096];
CRITICAL_SECTION cs;
char my_addr_txt [16], dst_addr_txt [16];
unsigned long my_addr, dst_addr;
unsigned short next_send_id, next_receive_id;
SOCKET ssin, sout;
HACMSTREAM has, hasd;
HANDLE hPlay, hRec[10], hTerminate, hData;
int segments, lock_size, input_buffer_size, output_buf_size;
HANDLE Thread [3];
DWORD id [3];
ACMSTREAMHEADER ahc, ahd;
WAVEFORMATEX wfx;
MPEG_WFX mwfx;
char listen_mode;
HWND talker_dlg;
void ErrB (char *msg, int x=0, HWND hwnd=0)
{
char str[128];
if (x) sprintf(str, "%s, code: %X", msg, x);
else sprintf(str, "%s", msg);
MessageBox(hwnd, str, 0, 0);
}
void release_vars (void)
{
DeleteCriticalSection (&cs);
CloseHandle (hPlay);
CloseHandle (hTerminate);
CloseHandle (hData);
}
char init_vars (void)
{
hPlay = CreateEvent (0, 0, 0, 0);
if (hPlay)
{
for (int i=0;i<10;i++) hRec[i] = CreateEvent (0, 0, 0, 0);
if (hRec[0]&&hRec[1]&&hRec[2]&&hRec[3]&&hRec[4]&&hRec[5]&&hRec[6]&&hRec[7]&&hRec[8]&&hRec[9])
{
hTerminate = CreateEvent (0, 1, 0, 0);
if (hTerminate)
{
hData = CreateSemaphore(0, 0, 63, 0);
if (hData)
{
next_receive_id = 0;
next_send_id = 1;
my_addr = 0;
memset (&mwfx, 0, sizeof (MPEG_WFX));
mwfx.wfx.wFormatTag = 85;
mwfx.wfx.nChannels = (stereo) ? 2 : 1;
mwfx.wfx.nSamplesPerSec = 11025;
mwfx.wfx.nAvgBytesPerSec = (band==0) ? 1000 : ((band==1) ? 2000 : 2500);
mwfx.wfx.nBlockAlign = 1;
mwfx.wfx.wBitsPerSample = 0;
mwfx.wfx.cbSize = 12;
// only 11025hz; adjust channels for number of channels
// for 20kbit: data[6]=4,data[7]=1,data[8]=2, avgbytespersec=2500
// THE 18kbit is not good since it requires 5 packets which is exactly as the 20kbit which is better
// for 18kbit: data[6]=0xD4,data[7]=1,data[8]=4,avg=2250
// for 16kbit: data[6]=0x68,avg=2000
// for 8kbit: data[6]=0x34,data[8]=1, avg=1000
mwfx.data[0] = 1;
mwfx.data[2] = 2;
mwfx.data[10] = 0x71;
mwfx.data[11] = 5;
switch (band)
{
case 0:
mwfx.data[6] = 0x34;
mwfx.data[8] = 1;
break;
case 1:
mwfx.data[6] = 0x68;
mwfx.data[8] = 1;
break;
case 2:
mwfx.data[6] = 4;
mwfx.data[7] = 1;
mwfx.data[8] = 2;
break;
}
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = (stereo) ? 2 : 1;
wfx.nSamplesPerSec = 11025;
wfx.nAvgBytesPerSec = (stereo) ? 44100 : 22050;
wfx.nBlockAlign = (stereo) ? 4 : 2;
wfx.wBitsPerSample = 16;
wfx.cbSize = 0;
InitializeCriticalSection (&cs);
index_put = 0;
index_take = -1;
queue_size = 0;
dbl = false;
segments = 4;
input_buffer_size = (stereo)?44100:22050;
lock_size = (stereo)?11024:5512;
return (1);
}
//CloseHandle (hTerminate);
}
//CloseHandle (hRec);
}
//CloseHandle (hPlay);
}
return (0);
}
char init_threads (void)
{
Thread[0] = CreateThread (0, 0, sender, 0, 0, &id[0]);
if (Thread[0])
{
Thread[1] = CreateThread (0, 0, player, 0, CREATE_SUSPENDED, &id[1]);
if (Thread[1])
{
Thread[2] = CreateThread (0, 0, receiver, 0, CREATE_SUSPENDED, &id[2]);
if (Thread[2]) return (1);
}
}
SetEvent (hTerminate);
return (0);
}
void close_threads (void)
{
SetEvent (hTerminate);
ResumeThread (Thread[1]);
ResumeThread (Thread[2]);
WaitForMultipleObjects (3, Thread, 1, INFINITE);
}
char init_all (void)
{
if (init_vars ())
{
if (init_sound ())
{
if (init_sockets ())
{
if (init_threads ()) return (1);
}
else ErrB ("socket problem");
close_sound ();
}
else ErrB ("sound problem");
release_vars ();
}
else ErrB ("varialbe problem");
return (0);
}
void close_all (void)
{
close_threads ();
close_sound ();
close_sockets ();
}
int WINAPI WinMain (HINSTANCE h1, HINSTANCE h2, LPSTR cmd, int show)
{
int r;
// after much thought, it seems just right to give ourselves a boost
// and anyway, we don't waste that much cycles
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
band = 0;
r = DialogBox (h1, MAKEINTRESOURCE (IDD_ADDRESS), 0, (DLGPROC) addr_dialog);
switch (r)
{
case 0 :
ErrB ("operation canceled");
break;
case 1:
if (init_all ())
{
r = DialogBox (h1, MAKEINTRESOURCE (IDD_TALK), 0, (DLGPROC) talk_dialog);
if (r) ErrB ("failed to create dialog box, aborting");
close_all ();
}
else ErrB ("init failed");
break;
case -1 :
ErrB ("failed to create first dialog box, aborting");
break;
}
ExitProcess (0);
return (0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -