声音格式转化问题(200分)

  • 主题发起人 主题发起人 yaoyao227
  • 开始时间 开始时间
Y

yaoyao227

Unregistered / Unconfirmed
GUEST, unregistred user!
1、waveOutOpen只能用WAVE_FORMAT_PCM吗?我用其他格式(WAVE_FORMAT_DVI_ADPCM)老是返回32
2、用acmStreamOpen每次都返回512,acmStreamOpen(&hstr1, had,inFormat,OutFormat,NULL, NULL, 0,ACM_STREAMOPENF_NONREALTIME);可能是什么错误啊
 
不会,帮你顶
 
没人答吗?
 
waveOutOpen是个API
 
不会呀,我刚写了一个
type
TACMWaveFormat = packed record
case integer of
0 : (Format : TWaveFormatEx);
1 : (RawData : Array[0..128] of byte);
end;

var
FormatIn,FormatOut: TACMWaveFormat ;
//----------------------------------------
//打开
//----------------------------------------
function OpenStream: boolean ;
var
mmr: mmresult ;
outSize : DWord ;
begin

result := false ;
FStartOfStream := true ;

mmr := acmStreamOpen(@FStreamhandle,0, FormatIn.Format, FormatOut.Format, nil, 0, 0, 0 );
if mmr <> 0 then
exit ;
//在此处出现错误 mmr = 215
mmr := acmStreamSize(FStreamHandle, InputBufferSize, OutputBufferSize, ACM_STREAMSIZEF_SOURCE);
if mmr <> 0 then
exit ;


GetMem(BufferIn, InputBufferSize);
Getmem(BufferOut, OutputBufferSize);
try
BuildHeader;
mmr := acmStreamPrepareHeader(FStreamHandle, FStreamHeader, 0);
if mmr <> 0 then
exit ;
except
Freemem(BufferIn);
Freemem(BufferOut);
exit;
end;

result := true ;
end;

//但是好象只能支持8位,单声道的 ,我现在也郁闷中.....
 
我在MSDN下运行其自带的acmapp都可以,我照着参数写的一样都不行
我需要由WAVE_FORMAT_DVI_ADPCM转化为pcm格式。
还问一下,我要播放WAVE_FORMAT_DVI_ADPCM(转化为pcm后播放),那么Waveoutopen中的格式用WAVE_FORMAT_DVI_ADPCM还是pcm格式啊?
 
yaoyao227把你压缩的代码给我看一下啊,我的就是压不成功,打开流时老是返回错误
 
C++写的
//压缩/解压的入口函数
DWORD DecodeSound::DecodeAcmSound(char* in, int inLen, WAVEFORMATEX* inFormat, char* out, int* outLen, WAVEFORMATEX* OutFormat)
{
WORD wFormatTag = inFormat->wFormatTag;
// Now we locate a CODEC that supports the destination format tag
HACMDRIVERID hadid = find_driver(wFormatTag, inFormat->nSamplesPerSec, inFormat->wBitsPerSample);


if (hadid == NULL) {
MessageBox(NULL,&quot;No driver found&quot;,&quot;find_driver ERROR&quot;,MB_OK);
return ET_SOUND;

}

// open the driver
HACMDRIVER had = NULL;
// MMSYSERR_INVALPARAM
MMRESULT mmr;

// open the driver
mmr = acmDriverOpen(&had, hadid, 0);

if (mmr) {
MessageBox(NULL,&quot;Failed to open driver&quot;,&quot;acmDriverOpen ERROR&quot;,MB_OK);
return ET_SOUND;
}

// open the conversion stream
// Note the use of the ACM_STREAMOPENF_NONREALTIME flag. Without this
// some software compressors will report error 512 - not possible
HACMSTREAM hstr1;

mmr = acmStreamOpen(&hstr1,
had, // driver handle ??NULL
inFormat, // source format
OutFormat, // destination format
NULL, // no filter
NULL, // no callback
0, // instance data (not used)
ACM_STREAMOPENF_NONREALTIME);
// flags
//MMSYSERR_NOTSUPPORTED = 8;
if (mmr) {
MessageBox(NULL,&quot;Failed to open acmstream&quot;,&quot;acmStreamOpen ERROR&quot;,MB_OK);
//printf(&quot;Failed to open a stream todo
PCM to driver format conversion/n&quot;);

return ET_SOUND;

}


DWORD dwDstBytes = inFormat->nAvgBytesPerSec * OutFormat->nSamplesPerSec / OutFormat->nSamplesPerSec;
dwDstBytes = dwDstBytes ;
// add a little room
// fill in the conversion info
ACMSTREAMHEADER strhdr1;

memset(&strhdr1, 0, sizeof(strhdr1));

strhdr1.cbStruct = sizeof(strhdr1);


strhdr1.pbSrc = (BYTE*)in;//pDstData;
//?? the source data to convert
strhdr1.cbSrcLength = inLen;
strhdr1.pbDst = (BYTE*)out;
//??test
strhdr1.cbDstLength = *outLen;//OutFormat->nAvgBytesPerSec;

// prep the header
mmr = acmStreamPrepareHeader(hstr1, &strhdr1, 0);

if (mmr)
{
return ET_SOUND;
}

// convert the data
mmr = acmStreamConvert(hstr1, &strhdr1, ACM_STREAMCONVERTF_BLOCKALIGN);// 0
if (mmr) {
return ET_SOUND;
}
acmStreamUnprepareHeader(hstr1, &strhdr1, 0);
//Close Stream
mmr = acmStreamClose(hstr1, 0);

//Close Driver
mmr = acmDriverClose(had, 0);

*outLen = strhdr1.cbDstLengthUsed;
//转化后的长度

// g_kAudioOut.write(out,*outLen); //logo add for test

return NO_ERR;
}

// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
BOOL CALLBACK find_format_enum(HACMDRIVERID hadid, LPACMFORMATDETAILS pafd, DWORD dwInstance, DWORD fdwSupport)
{
FIND_DRIVER_INFO* pdi = (FIND_DRIVER_INFO*) dwInstance;

if ((pafd->dwFormatTag == (DWORD)pdi->wFormatTag) &&
(pafd->pwfx->nSamplesPerSec == pdi->nSamplesPerSec)&&
(pafd->pwfx->wBitsPerSample == pdi->wBitsPerSample)){ //
// found it
pdi->hadid = hadid;

printf(&quot;
%4.4lXH, %s/n&quot;, pafd->dwFormatTag, pafd->szFormat);

return FALSE;
// stop enumerating
}
return TRUE;
// continue enumerating
}
// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
BOOL CALLBACK find_driver_enum(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport)
{
FIND_DRIVER_INFO* pdi = (FIND_DRIVER_INFO*) dwInstance;

if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)
printf(&quot;多格式转换/n&quot;);


// open the driver
HACMDRIVER had = NULL;

HRESULT mmr = acmDriverOpen(&had, hadid, 0);

if (mmr) {
// some error
MessageBox(NULL,&quot;Failed to open driver&quot;,&quot;acmStreamConvert ERROR&quot;,MB_OK);
return FALSE;
// stop enumerating
}

// enumerate the formats it supports
DWORD dwSize = 0;

mmr = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);

if (mmr)
{
MessageBox(NULL,&quot;acmMetrics ERROR&quot;,&quot;acmMetrics ERROR&quot;,MB_OK);
return FALSE;
}
if (dwSize < sizeof(WAVEFORMATEX)){
dwSize = sizeof(WAVEFORMATEX);
// for MS-PCM
}

WAVEFORMATEX* pwf = (WAVEFORMATEX*) malloc(dwSize);

memset(pwf, 0, dwSize);

pwf->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX);

pwf->wFormatTag = pdi->wFormatTag;

pwf->nSamplesPerSec = pdi->nSamplesPerSec;
pwf->wBitsPerSample = pdi->wBitsPerSample;
ACMFORMATDETAILS fd;

memset(&fd, 0, sizeof(fd));

fd.cbStruct = sizeof(fd);

fd.pwfx = pwf;

fd.cbwfx = dwSize;

fd.dwFormatTag = pdi->wFormatTag;


mmr = acmFormatEnum(had, &fd, find_format_enum, (DWORD)(VOID*)pdi, 0);
//ACM_FORMATENUMF_WFORMATTAG
free(pwf);

acmDriverClose(had, 0);

if (pdi->hadid || mmr) {
// found it or some error
return FALSE;
// stop enumerating
}

return TRUE;
// continue enumeration
}

// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
HACMDRIVERID DecodeSound::find_driver(WORD wFormatTag, DWORD nSamplesPerSec, WORD wBitsPerSample)
{
FIND_DRIVER_INFO fdi;

fdi.hadid = NULL;

fdi.wFormatTag = wFormatTag;

fdi.nSamplesPerSec = nSamplesPerSec;
fdi.wBitsPerSample = wBitsPerSample;
MMRESULT mmr = acmDriverEnum(find_driver_enum, (DWORD)(VOID*)&fdi, 0);

if (mmr) return NULL;

return fdi.hadid;

}
//调用压缩/解压(我的是解压ADPCM to PCM)
//标准格式
dstFormat = (WAVEFORMATEX*)new char[18];
dstFormat->cbSize = 0;
dstFormat->wFormatTag = WAVE_FORMAT_PCM;
// pcm
dstFormat->nChannels = 1; // mono
dstFormat->nSamplesPerSec = 8000; // 11.025 kHz
dstFormat->wBitsPerSample = 8; // 8 bit
dstFormat->nBlockAlign = dstFormat->nChannels * dstFormat->wBitsPerSample / 8;
dstFormat->nAvgBytesPerSec = dstFormat->nSamplesPerSec * dstFormat->nBlockAlign;

//解压后的格式
dwDataLen = dwG72x * 4; // 压缩率为 4
srcFormat = (WAVEFORMATEX*)new char[20];
srcFormat->nChannels = 1;
srcFormat->wFormatTag = WAVE_FORMAT_DVI_ADPCM;
srcFormat->nSamplesPerSec = 8000;
srcFormat->wBitsPerSample = 4;
srcFormat->nBlockAlign = 256;
srcFormat->nAvgBytesPerSec = 4055;
srcFormat->cbSize = 2;
//注意,不同格式 不同
unsigned char extra060[2] = { 0xF9, 0x01 };

for(i=0;i<srcFormat->cbSize;i++) {
*((unsigned char *)srcFormat+18+i) = extra060;

}
//压缩或解压
m_DecodeSound->DecodeAcmSound(
(char*)pbG72x, dwG72x, srcFormat,
(char*)pbDataBuf, (int*) &dwDataLen, dstFormat);
 
写错一句注释
//解压后的格式 为 //解压前的格式
 
标准的PCM格式,dstFormat->wBitsPerSample = 8;还是dstFormat->wBitsPerSample = 16?
 
为何我压缩后,再解压.所得的大小比原始大小要小一些.这是什么原因呢.
我用的是PCM -------------WAVE_FORMAT_DSPGROUP_TRUESPEECH-----------PCM
可是我解压后的数据要比原始数据小一点.这是何道理?
 
改天帮我看一下源码
 
标准的PCM格式,dstFormat->wBitsPerSample = 8 我用的是8,由你的采样位数决定,我得到的声音数据的格式是8,我必须解压成8位才可以播放。可以看你的代码。我邮箱
wuruijuan11@163.com
 
好的,因为程序比较大,所以我是单独做的一个用来测试的小程序,然后因为不知毛病出在哪里所以改来改去,有点乱了,我下午发给你,你帮我看一下
 
我看过一些资料上说虽然是PCM但很多管理器只支持一种标准格式的PCM吗?自已定的PCM如11025,8 这样的,要先转成标准的PCM 8000,?后才能再转成其他的格式吗?
 
我刚才试了一下给上面给出的代码。在我这里却打不开流。
 
我之前打不开流是因为下面的代码不对, 其中{ 0xF9, 0x01 };是根据不同格式找出的,不一定是两个(srcFormat->cbSize = 2;决定),你根据你的格式找一下,必须赋值!
unsigned char extra060[2] = { 0xF9, 0x01 };

for(i=0;i<srcFormat->cbSize;i++) {
*((unsigned char *)srcFormat+18+i) = extra060;

}
 
To yymmartin
(自已定的PCM如11025,8 这样的,要先转成标准的PCM 8000,?后才能再转成其他的格式吗)
不是的,因为我得到的声音数据采样位数为8000,所以我用8000,你根据你得到的数据的采样位数定。
 
我用的格式跟你的是一样的呀。。你是说不需要先转成PCM 8000 ?可是我直接用PCM 11025 ,8 转换成 WAVE_FORMAT_DSPGROUP_TRUESPEECH ,老是打开流时就失败了。现在先不说这个你帮我看了我发给你例子程序了吗?我压缩完后,解压后的大小为什么比压缩前的大小要小?先帮我看一下先
 
后退
顶部