⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threads.cpp

📁 a file about net phone based on IP,write by VC++.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
   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 + -