www.pudn.com > 使用IP网络聊天的VOIP源码.zip > sound.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#include #include #include #include #include "defines.h" void ErrB (char*, int=0, HWND=0); extern bool stereo, use_primary; extern HACMSTREAM has, hasd; extern HANDLE hPlay, hRec[10]; extern ACMSTREAMHEADER ahc, ahd; extern WAVEFORMATEX wfx; extern MPEG_WFX mwfx; extern int input_buffer_size, segments, output_buf_size; extern char decomp_buf[44100]; extern char comped_buf[4096]; extern char acmbuf[44100]; extern char output_buffer[4096]; LPDIRECTSOUND lpds; LPDIRECTSOUNDBUFFER lpdsb; LPDIRECTSOUNDNOTIFY lpdsn; LPDIRECTSOUNDCAPTURE lpdsc; LPDIRECTSOUNDCAPTUREBUFFER lpdscb; LPDIRECTSOUNDNOTIFY lpdsnc; bool zero_output_buffer (void) { HRESULT hr; LPVOID pv1, pv2; DWORD cb1, cb2; hr = lpdsb->Lock(0, 0, &pv1, &cb1, &pv2, &cb2, DSBLOCK_ENTIREBUFFER); if (hr==DS_OK) { memset(pv1, 0, cb1); if (pv2) memset(pv2, 0, cb2); lpdsb->Unlock(pv1, cb1, pv2, cb2); } return (hr==DS_OK); } bool set_capture_events (int segs) { DSBPOSITIONNOTIFY dsbnn[10]; HRESULT hr; int i; for (i=0; i SetNotificationPositions(segs, dsbnn); return (hr==DS_OK); } bool init_primary_buffer (void) { HRESULT hr; DSBUFFERDESC dsbd; dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = DSBCAPS_STICKYFOCUS|DSBCAPS_PRIMARYBUFFER; dsbd.dwBufferBytes = 0; dsbd.dwReserved = 0; dsbd.lpwfxFormat = 0; hr = lpds->CreateSoundBuffer(&dsbd, &lpdsb, 0); if (hr==DS_OK) { hr = lpdsb->SetFormat(&wfx); if (hr==DS_OK) { DSBCAPS dsbc; dsbc.dwSize = sizeof(dsbc); lpdsb->GetCaps(&dsbc); output_buf_size = dsbc.dwBufferBytes; return true; } lpdsb->Release(); } lpdsb = 0; return false; } bool set_primary_buffer_format (void) { LPDIRECTSOUNDBUFFER primary; DSBUFFERDESC dsbd; HRESULT hr; dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbd.dwBufferBytes = 0; dsbd.dwReserved = 0; dsbd.lpwfxFormat = 0; hr = lpds->CreateSoundBuffer(&dsbd, &primary, 0); if (hr==DS_OK) { hr = primary->SetFormat(&wfx); primary->Release(); } return (hr==DS_OK); } bool init_secondary_buffer (void) { #define BUFFER_SIZE 20*1024 HRESULT hr; DSBUFFERDESC dsbd; if (set_primary_buffer_format()) { dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = DSBCAPS_GLOBALFOCUS|DSBCAPS_STICKYFOCUS|DSBCAPS_GETCURRENTPOSITION2; dsbd.dwBufferBytes = BUFFER_SIZE; dsbd.dwReserved = 0; dsbd.lpwfxFormat = &wfx; hr = lpds->CreateSoundBuffer(&dsbd, &lpdsb, 0); if (hr==DS_OK) { output_buf_size = BUFFER_SIZE; //zero_output_buffer(); DSBCAPS dsbc; dsbc.dwSize = sizeof(dsbc); lpdsb->GetCaps(&dsbc); //lpdsb->Play(0, 0, DSBPLAY_LOOPING); return true; } } lpdsb = 0; return false; #undef BUFFER_SIZE } bool init_wave_out_ds (HWND hwnd) { HRESULT hr; hr = DirectSoundCreate(0, &lpds, 0); if (hr==DS_OK) { ShowWindow(hwnd, SW_SHOW); hr = lpds->SetCooperativeLevel(hwnd, (use_primary)?DSSCL_WRITEPRIMARY:DSSCL_PRIORITY); if (hr==DS_OK) { if (use_primary) if (init_primary_buffer()) return true; else MessageBox(hwnd, "err init using primary buf", 0, 0); else if (init_secondary_buffer()) return true; else MessageBox(hwnd, "err using secondary buffer", 0, 0); } else MessageBox(hwnd, "unable to set cooperative level", 0, 0); lpds->Release(); } else MessageBox(hwnd, "open sound device failed", 0, 0); lpdsb=0; lpds=0; return false; } void close_wave_out_ds (void) { if (lpdsb) lpdsb->Release(); if (lpds) lpds->Release(); lpdsb = 0; lpds = 0; } bool init_wave_in_ds (HWND hwnd) { HRESULT hr; hr = DirectSoundCaptureCreate(0, &lpdsc, 0); if (hr==DS_OK) { DSCBUFFERDESC dsbcd; dsbcd.dwSize = sizeof(dsbcd); dsbcd.dwFlags = 0; dsbcd.dwBufferBytes = input_buffer_size; dsbcd.dwReserved = 0; dsbcd.lpwfxFormat = &wfx; hr = lpdsc->CreateCaptureBuffer(&dsbcd, &lpdscb, 0); if (hr==DS_OK) { lpdscb->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&lpdsnc); if (hr==S_OK) { if (set_capture_events(segments)) return true; else ErrB("err setting points", hr, hwnd); lpdsnc->Release(); } else ErrB("query notify", hr, hwnd); lpdscb->Release(); } else ErrB("capture buffer", hr, hwnd); lpdsc->Release(); } else ErrB("capture device", hr, hwnd); lpdsnc = 0; lpdscb = 0; lpdsc = 0; return false; } void close_wave_in_ds (void) { if (lpdscb) { lpdscb->Stop(); lpdscb->Release(); } if (lpdsnc) lpdsnc->Release(); if (lpdsc) lpdsc->Release(); lpdscb = 0; lpdsnc = 0; lpdsc = 0; } char init_acm_stream (void) { long r; r = acmStreamOpen (&has, NULL, &wfx, &mwfx.wfx, 0, 0, 0, 0); if (!r) { memset (&ahc, 0, sizeof (ACMSTREAMHEADER)); ahc.cbStruct = sizeof (ACMSTREAMHEADER); ahc.pbSrc = (BYTE *) acmbuf; ahc.cbSrcLength = 44100; ahc.pbDst = (BYTE *) output_buffer; ahc.cbDstLength = 4096; r = acmStreamPrepareHeader (has, &ahc, 0); if (!r) return 1; acmStreamClose (has, 0); } return (0); } void close_acm_stream (void) { ahc.cbSrcLength = 44100; ahc.cbDstLength = 4096; acmStreamUnprepareHeader (has, &ahc, 0); acmStreamClose (has, 0); } char init_acm_stream_decomp (void) { long r; r = acmStreamOpen (&hasd, NULL, &mwfx.wfx, &wfx, 0, 0, 0, 0); if (!r) { memset (&ahd, 0, sizeof (ACMSTREAMHEADER)); ahd.cbStruct = sizeof (ACMSTREAMHEADER); ahd.pbSrc = (BYTE *) comped_buf; ahd.cbSrcLength = 4096; ahd.pbDst = (BYTE *) decomp_buf; ahd.cbDstLength = 44100; r = acmStreamPrepareHeader (hasd, &ahd, 0); if (!r) return 1; acmStreamClose (hasd, 0); } return (0); } void close_acm_stream_decomp (void) { ahd.cbSrcLength = 4096; ahd.cbDstLength = 44100; acmStreamUnprepareHeader (hasd, &ahd, 0); acmStreamClose (hasd, 0); } void close_sound (void) { close_acm_stream_decomp(); close_acm_stream (); close_wave_in_ds (); close_wave_out_ds (); } char init_sound (void) { if (init_acm_stream_decomp ()) { if (init_acm_stream()) return (1); else ErrB("init acm decomp stream"); close_acm_stream_decomp(); } else ErrB ("error initializing acm stream"); return (0); }