我參照了
http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnarmulmed/html/msdn_codec.asp
及
http://david.weekly.org/code/mp3acm.html 試圖將(預設)PCM的格式wave檔轉為(預設)G.711 ALAW的格式,
程式執行是順利,但所產生的wave,卻是無法開啟。 以下是我的code:
// convert a PCM wave to G.711 format
#include
#include
#include // Multimedia registration
#include // Audio Compression Manager
#include
#include <math.h>
#include #define INPUT_FILE "in.wav"
#define BLOCK_SIZE 1000
#define OUTPUT_FILE "out.wav" // Locate a driver that supports a given format and return its ID
typedef struct {
HACMDRIVERID hadid;
WORD wFormatTag;
} FIND_DRIVER_INFO; // callback function for format enumeration
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) {
// found it
pdi->hadid = hadid;
return FALSE; // stop enumerating
} return TRUE; // continue enumerating
} // callback function for driver enumeration
BOOL CALLBACK find_driver_enum(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport)
{
FIND_DRIVER_INFO* pdi = (FIND_DRIVER_INFO*) dwInstance; // open the driver
HACMDRIVER had = NULL;
MMRESULT mmr = acmDriverOpen(&had, hadid, 0);
if (mmr) { // some error
return FALSE; // stop enumerating } // enumerate the formats it supports
DWORD dwSize = 0;
mmr = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
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;
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);
free(pwf);
acmDriverClose(had, 0);
if (pdi->hadid || mmr) {
// found it or some error
return FALSE; // stop enumerating
} return TRUE; // continue enumeration
} // locate the first driver that supports a given format tag
HACMDRIVERID find_driver(WORD wFormatTag)
{
FIND_DRIVER_INFO fdi;
fdi.hadid = NULL;
fdi.wFormatTag = wFormatTag;
MMRESULT mmr = acmDriverEnum(find_driver_enum, (DWORD)(VOID*)&fdi, 0);
if (mmr) return NULL;
return fdi.hadid;
} // get a description of the first format supported for a given tag
WAVEFORMATEX* get_driver_format(HACMDRIVERID hadid, WORD wFormatTag)
{
// open the driver
HACMDRIVER had = NULL;
MMRESULT mmr = acmDriverOpen(&had, hadid, 0);
if (mmr) {
return NULL;
} // allocate a structure for the info
DWORD dwSize = 0;
mmr = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
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 = wFormatTag; ACMFORMATDETAILS fd;
memset(&fd, 0, sizeof(fd));
fd.cbStruct = sizeof(fd);
fd.pwfx = pwf;
fd.cbwfx = dwSize;
fd.dwFormatTag = wFormatTag; // set up a struct to control the enumeration
FIND_DRIVER_INFO fdi;
fdi.hadid = NULL;
fdi.wFormatTag = wFormatTag; mmr = acmFormatEnum(had, &fd, find_format_enum, (DWORD)(VOID*)&fdi, 0);
acmDriverClose(had, 0);
if ((fdi.hadid == NULL) || mmr) {
free(pwf);
return NULL;
}
return pwf;
} void PCMtoALAW()
{
// Select a format to convert to
WORD wFormatTag = WAVE_FORMAT_ALAW; // Now we locate a CODEC that supports the destination format tag
HACMDRIVERID hadid = find_driver(wFormatTag);
if (hadid == NULL) {
printf("No driver found\n");
exit(1);
}
printf("Driver found (hadid: %4.4lXH)\n", hadid); // show some information about the driver
ACMDRIVERDETAILS dd;
dd.cbStruct = sizeof(dd);
MMRESULT mmr = acmDriverDetails(hadid, &dd, 0);
printf(" Short name: %s\n", dd.szShortName);
printf(" Long name: %s\n", dd.szLongName);
printf(" Copyright: %s\n", dd.szCopyright);
printf(" Licensing: %s\n", dd.szLicensing);
printf(" Features: %s\n", dd.szFeatures); // get the details of the format
// Note: this is just the first of one or more possible formats for the given tag
WAVEFORMATEX* pwfDrv = get_driver_format(hadid, wFormatTag);
if (pwfDrv == NULL) {
printf("Error getting format info\n");
exit(1);
}
printf("Driver format: %u bits, %lu samples per second\n", pwfDrv->wBitsPerSample, pwfDrv->nSamplesPerSec); // get a PCM format tag the driver supports
// Note: we just pick the first supported PCM format which might not really
// be the best choice.
WAVEFORMATEX* pwfPCM = get_driver_format(hadid, WAVE_FORMAT_PCM);
if (pwfPCM == NULL) {
printf("Error getting PCM format info\n");
exit(1);
}
printf("PCM format: %u bits, %lu samples per second\n", pwfPCM->wBitsPerSample, pwfPCM->nSamplesPerSec); // open the driver
HACMDRIVER had = NULL;
mmr = acmDriverOpen(&had, hadid, 0);
if (mmr) {
printf("Failed to open driver\n");
exit(1);
} // 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 hstr = NULL;
mmr = acmStreamOpen(&hstr,
had, // driver handle
pwfPCM, // source format
pwfDrv, // destination format
NULL, // no filter
NULL, // no callback
0, // instance data (not used)
ACM_STREAMOPENF_NONREALTIME); // flags
if (mmr) {
printf("Failed to open a stream to do PCM to driver format conversion\n");
exit(1);
} //--------------------------------------------------------------------------------
// open file
FILE *fpIn = fopen( INPUT_FILE, "rb" );
if( fpIn == NULL ){
assert( !"can't open WAVE file!" );
return E_FAIL;
}
// find out how big the decompressed buffer will be
unsigned long rawbufsize = 0;
mmr = acmStreamSize( hstr, BLOCK_SIZE, &rawbufsize, ACM_STREAMSIZEF_SOURCE );
assert( mmr == 0 );
assert( rawbufsize > 0 );
// allocate our I/O buffers
LPBYTE srcbuf = (LPBYTE) LocalAlloc( LPTR, BLOCK_SIZE );
LPBYTE rawbuf = (LPBYTE) LocalAlloc( LPTR, rawbufsize );
//-------------------------------------------------------------------------------- // fill in the conversion info
ACMSTREAMHEADER strhdr;
memset(&strhdr, 0, sizeof(strhdr));
strhdr.cbStruct = sizeof(strhdr);
strhdr.pbSrc = srcbuf;
strhdr.cbSrcLength = BLOCK_SIZE;
strhdr.pbDst = rawbuf;
strhdr.cbDstLength = rawbufsize; // prep the header
mmr = acmStreamPrepareHeader(hstr, &strhdr, 0);
if (mmr) printf(" error : pre the header!!!\n"); // let's dump this data off to disk (for debug checking!)
FILE *fpOut = fopen( OUTPUT_FILE, "wb" );
if( fpOut == NULL ){
assert( !"can't output output PCM!" );
return E_FAIL;
} printf("Converting to final format...\n"); while(1) {
// suck in some MP3 data
int count = fread( srcbuf, 1, BLOCK_SIZE, fpIn );
if( count != BLOCK_SIZE ) break;
//if (count<=0)
// convert the data
mmr = acmStreamConvert(hstr, &strhdr, 0);
if (mmr) {
printf("Failed to do PCM to driver format conversion\n");
exit(1);
} // write the decoded PCM to disk
count = fwrite( rawbuf, 1, strhdr.cbDstLengthUsed, fpOut );
//printf("%d\n",strhdr.cbDstLengthUsed);
assert( count == strhdr.cbDstLengthUsed );
} printf("Converted OK\n"); // close the stream and driver
mmr = acmStreamClose(hstr, 0);
mmr = acmDriverClose(had, 0);
fclose( fpIn );
fclose( fpOut );
mmr = acmStreamUnprepareHeader( hstr, &strhdr, 0 );
assert( mmr == 0 );
LocalFree(rawbuf);
LocalFree(srcbuf);
mmr = acmStreamClose( hstr, 0 );
assert( mmr == 0 ); }
期望好心的大大給予協助,謝謝
發表人 -