请教音频混音代码?

yewsoft 2002-12-18 11:41:16
两个PCM音频内容,要求混音!
我现在的做法是直接将Wave值相加除二,这显然是不对的!
求教一种恰当的方法:
能给出代码的我将重谢!
任何相关内容提供都将被加分
...全文
367 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
shinesi 2002-12-18
  • 打赏
  • 举报
回复
简单的混音就是相加除二

如果你要考虑两个声音的距离等其它因素,DirectSound有这个功能
duwenyong 2002-12-18
  • 打赏
  • 举报
回复
class CWaveMix
{
public:
void MixData(PBYTE lpWaveSrc[],PBYTE lpWavDst,int iChannels,WORD wLen);
CWaveMix();
virtual ~CWaveMix();
int Open(char*); //打开一个WAV文件
int Play(HWND); //播放一个WAV文件
int Add(char*); //往正在播放的WAV设备中添加WAV 文件
int Stop(); //停止播放
int Close(); //关闭设备
int Continue();

DWORD DataSize;
WAVDATA* lpData;
private:
BOOL OpenFlage;
HGLOBAL hData;
DWORD DataSize_start;

PCMWAVEFORMAT pFormat;
WAVEHDR WaveHead;
HWAVEOUT hWaveOut;

int m_Channels;
};

CWaveMix::CWaveMix()
{
memset(this,0,sizeof(CWaveMix));
}

CWaveMix::~CWaveMix()
{
Close();
}

int CWaveMix::Open(char* name)
{
HMMIO hMmio;
MMCKINFO pinfo;
MMCKINFO cinfo;

if(hMmio)
Close();

//打开WAV文件,返回一个HMMIO句柄
hMmio=mmioOpen(name,NULL,MMIO_READ);
if(!hMmio)
return FALSE;
OpenFlage=1;

//查找父块"wave";
pinfo.fccType=mmioFOURCC('W','A','V','E');
if(mmioDescend(hMmio,&pinfo,NULL,MMIO_FINDRIFF))
goto FALSE_END;

//查找子块"fmt" parent"riff";
cinfo.ckid=mmioFOURCC('f','m','t',' ');
if(mmioDescend(hMmio,&cinfo,&pinfo,MMIO_FINDCHUNK))
goto FALSE_END;

mmioRead(hMmio,(LPSTR)&pFormat,sizeof(PCMWAVEFORMAT));//cinfo.cksize);
if(pFormat.wf.wFormatTag!=WAVE_FORMAT_PCM)
goto FALSE_END;

//跳入块"FMT"
mmioAscend(hMmio,&cinfo,0);

//查找数据块
cinfo.ckid=mmioFOURCC('d','a','t','a');
if(mmioDescend(hMmio,&cinfo,&pinfo,MMIO_FINDCHUNK))
goto FALSE_END;
DataSize=cinfo.cksize;
//读取数据
hData=GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE,DataSize);
lpData=(WAVDATA*)GlobalLock(hData);
if( !hData || !lpData ) goto FALSE_END;
if(mmioRead(hMmio,(HPSTR)lpData,DataSize)!=(LRESULT)DataSize)
goto FALSE_END;

//close and return
mmioClose(hMmio,MMIO_FHOPEN);
return TRUE;

FALSE_END:
if(hMmio)mmioClose(hMmio,MMIO_FHOPEN);
if(lpData)LocalUnlock(hData);
if(hData)GlobalFree(hData);
memset(this,0,sizeof(CWaveMix));
return 0;
}

int CWaveMix::Play(HWND hP)
{
if(!OpenFlage)
return FALSE;

//检测系统播放功能
if(waveOutOpen(NULL,WAVE_MAPPER,(WAVEFORMATEX*)&pFormat,NULL,NULL,WAVE_FORMAT_QUERY))
return Close();

if(waveOutOpen(&hWaveOut,WAVE_MAPPER,(WAVEFORMATEX*)&pFormat,(DWORD)hP,0,CALLBACK_WINDOW))
return Close();

WaveHead.lpData=(LPSTR)lpData;
WaveHead.dwBufferLength=DataSize;
WaveHead.dwFlags=0L;
WaveHead.dwLoops=0L;
DataSize_start=DataSize;

//往WAV设备中添加数据
if(waveOutPrepareHeader(hWaveOut,&WaveHead, sizeof(WAVEHDR)))
return Close();

if(waveOutWrite(hWaveOut,&WaveHead,sizeof(WAVEHDR)))
return Close();

return TRUE;
}

int CWaveMix::Continue()
{
CWaveMix wav;
if(!wav.Open("2.wav"))
return FALSE;
memcpy(lpData,wav.lpData,DataSize);
// WaveHead.lpData=(LPSTR)wav.lpData;
// WaveHead.dwBufferLength=wav.DataSize;
if(waveOutPrepareHeader(hWaveOut,&WaveHead, sizeof(WAVEHDR)))
return Close();
if(waveOutWrite(hWaveOut,&WaveHead,sizeof(WAVEHDR)))
return Close();
return TRUE;
}

//#define min(a, b) (((a) < (b)) ? (a) : (b))
int CWaveMix::Add(char* name)
{
register int x;
if(!OpenFlage)
return Open(name);

CWaveMix wav;
if(!wav.Open(name))
return FALSE;

MMTIME time;
//获得WAV文件当前播放位置
time.wType=TIME_BYTES;
if(waveOutGetPosition(hWaveOut,&time,sizeof(MMTIME)))
time.u.cb=0;
DWORD start=((time.u.cb>>1)<<1);
DWORD end=min(DataSize_start,wav.DataSize);
// DWORD end=wav.DataSize;
register WAVDATA* lpd=lpData+start;
for(register DWORD i=0;i<end;i++)
{
//将两组WAV文件数据相加,并检测数据大小是否合法,如果
//数据大小越界,则分别取最大值和最小值
x=(((*(lpd+i))+(*(wav.lpData+i))))-128;
if(x<0)
x=0;
if(x>255)
x=255;
*(lpd+i)=(BYTE)(x);
}
return TRUE;
}

int CWaveMix::Stop()
{
return !waveOutReset(hWaveOut);
}

int CWaveMix::Close()
{
if(hWaveOut)
{
waveOutReset(hWaveOut);
waveOutUnprepareHeader(hWaveOut,&WaveHead,sizeof(WAVEHDR));
waveOutClose(hWaveOut);
}


if(lpData)LocalUnlock(hData);
if(hData)GlobalFree(hData);
memset(this,0,sizeof(CWaveMix));
return 0;
}


void CWaveMix::MixData(PBYTE lpWavSrc[], PBYTE lpWavDst, int iChannels, WORD wLen)
{
int i,iSum;
for(int j=0;j<wLen;j++)
{
iSum=128;//静音时数值为128
for(i=0;i<iChannels;i++)
iSum=iSum+*(lpWavSrc[i]+j)-128;
if(iSum<0) iSum=0;
if(iSum>255) iSum=255;
*lpWavDst++=iSum;
}
}

duwenyong 2002-12-18
  • 打赏
  • 举报
回复
假设有4路Wave数据,目的缓冲区的大小为1378,混音子函数调用为 Mixer(lpDest,rgpCDdata,4,1378)。
下面给出混音子函数的实现。其中lpDest为目的缓冲区,rgWaveSrc为多路Wave数据源,iNumWaves为Wave数据源的通道数,wLen为目的缓冲区长度。
Void mixit(LPSAMPLE lpDest,LPSAMPLE rgWaveSrc[],int iNumWaves,WORD wLen)
{
int,,iSum;
WORD ctr;
ctr=0
While(wLen)
{
iSum=128;/*静音时数值为128*/
for(I=0;I<iNumWaves;I++=
iSum=iSum+*(rgWaveSrc[I]+ctr)-128;
PEG((int)0,iSum,(int)225);/*对转换结果处理*/
*lpDest++=iSum;
ctr++;
wLen--;
}
}

注意一点的是对于单声道数据一个字节表示一个采样值,采样值在0—255之间,各个通道的对应Wave数据相加后,就会溢出,还需要将相加结果转换成0—255之间的数值。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧