📄 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 <windows.h>
#include <mmsystem.h>
#include <dsound.h>
#include <mmreg.h>
#include <msacm.h>
#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<segs; i++) dsbnn[i].hEventNotify = hRec[i];
switch (segs)
{
case 2:
dsbnn[0].dwOffset = input_buffer_size/2 - ((stereo)?3:1);
dsbnn[1].dwOffset = input_buffer_size-1;
break;
case 3:
for (i=0; i<3; i++) dsbnn[i].dwOffset = (input_buffer_size/3)*(i+1)-1;
break;
case 4:
dsbnn[0].dwOffset = (stereo) ? 11023 : 5511;
dsbnn[1].dwOffset = (stereo) ? 22047 : 11023;
dsbnn[2].dwOffset = (stereo) ? 33071 : 16535;
dsbnn[3].dwOffset = input_buffer_size-1;
break;
case 10:
dsbnn[0].dwOffset = (stereo) ? 4407 : 2203;
for (i=1; i<9; i++) dsbnn[i].dwOffset = dsbnn[i-1].dwOffset+((stereo)?4408:2204);
dsbnn[9].dwOffset = input_buffer_size-1;
break;
}
hr = lpdsnc->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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -